mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
Merge branch 'ver4dev' of https://github.com/biveraxe/IoTManager into ver4dev
This commit is contained in:
@@ -17,7 +17,6 @@ void globalVarsSync() {
|
||||
valuesFlashJson = readFile(F("values.json"), 4096);
|
||||
valuesFlashJson.replace("\r\n", "");
|
||||
|
||||
|
||||
mqttPrefix = jsonReadStr(settingsFlashJson, F("mqttPrefix"));
|
||||
mqttRootDevice = mqttPrefix + "/" + chipId;
|
||||
jsonWriteStr_(settingsFlashJson, "root", mqttRootDevice);
|
||||
@@ -27,6 +26,7 @@ void globalVarsSync() {
|
||||
// jsonWriteStr_(ssidListHeapJson, "ssids_", ""); //метка для парсинга удалить
|
||||
}
|
||||
|
||||
//к удалению. не используется
|
||||
String getParamsJson() {
|
||||
String json;
|
||||
serializeJson(*getLocalItemsAsJSON(), json);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
TickerScheduler ts(END + 1);
|
||||
WiFiClient espClient;
|
||||
PubSubClient mqtt(espClient);
|
||||
StringCommand sCmd;
|
||||
|
||||
#ifdef ASYNC_WEB_SERVER
|
||||
AsyncWebServer server(80);
|
||||
#endif
|
||||
@@ -31,14 +31,15 @@ WebSocketsServer standWebSocket = WebSocketsServer(81);
|
||||
**********************************************************************************************************************/
|
||||
IoTGpio IoTgpio(0);
|
||||
|
||||
String settingsFlashJson = "{}"; // переменная в которой хранятся все настройки, находится в оперативной памяти и синхронизированна с flash памятью
|
||||
String valuesFlashJson = "{}"; // переменная в которой хранятся все значения элементов, которые необходимо сохранить на flash. Находится в оперативной памяти и синхронизированна с flash памятью
|
||||
String errorsHeapJson = "{}"; // переменная в которой хранятся все ошибки, находится в оперативной памяти только
|
||||
bool needSaveValues = false; // признак необходимости сбросить значения элементов на flash
|
||||
String settingsFlashJson = "{}"; // переменная в которой хранятся все настройки, находится в оперативной памяти и синхронизированна с flash памятью
|
||||
String valuesFlashJson = "{}"; // переменная в которой хранятся все значения элементов, которые необходимо сохранить на flash. Находится в оперативной памяти и синхронизированна с flash памятью
|
||||
String errorsHeapJson = "{}"; // переменная в которой хранятся все ошибки, находится в оперативной памяти только
|
||||
bool needSaveValues = false; // признак необходимости сбросить значения элементов на flash
|
||||
|
||||
// buf
|
||||
String orderBuf = "";
|
||||
String eventBuf = "";
|
||||
String mysensorBuf = "";
|
||||
|
||||
// wifi
|
||||
String ssidListHeapJson = "{}";
|
||||
@@ -69,8 +70,10 @@ String mqttRootDevice = "";
|
||||
// Time
|
||||
unsigned long unixTime = 0;
|
||||
unsigned long unixTimeShort = 0;
|
||||
String prevDate = "";
|
||||
bool firstTimeInit = true;
|
||||
|
||||
//unsigned long loopPeriod;
|
||||
// unsigned long loopPeriod;
|
||||
|
||||
bool isTimeSynch = false;
|
||||
Time_t _time_local;
|
||||
|
||||
40
src/Main.cpp
40
src/Main.cpp
@@ -16,10 +16,10 @@ void setup() {
|
||||
Serial.println();
|
||||
Serial.println(F("--------------started----------------"));
|
||||
|
||||
//создание экземпляров классов
|
||||
// myNotAsyncActions = new NotAsync(do_LAST);
|
||||
// создание экземпляров классов
|
||||
// myNotAsyncActions = new NotAsync(do_LAST);
|
||||
|
||||
//инициализация файловой системы
|
||||
// инициализация файловой системы
|
||||
fileSystemInit();
|
||||
Serial.println(F("------------------------"));
|
||||
Serial.println("FIRMWARE NAME " + String(FIRMWARE_NAME));
|
||||
@@ -27,16 +27,16 @@ void setup() {
|
||||
Serial.println("WEB VERSION " + getWebVersion());
|
||||
Serial.println(F("------------------------"));
|
||||
|
||||
//получение chip id
|
||||
// получение chip id
|
||||
setChipId();
|
||||
|
||||
//синхронизация глобальных переменных с flash
|
||||
// синхронизация глобальных переменных с flash
|
||||
globalVarsSync();
|
||||
|
||||
//подключаемся к роутеру
|
||||
// подключаемся к роутеру
|
||||
routerConnect();
|
||||
|
||||
//инициализация асинхронного веб сервера и веб сокетов
|
||||
// инициализация асинхронного веб сервера и веб сокетов
|
||||
#ifdef ASYNC_WEB_SERVER
|
||||
asyncWebServerInit();
|
||||
#endif
|
||||
@@ -44,7 +44,7 @@ void setup() {
|
||||
asyncWebSocketsInit();
|
||||
#endif
|
||||
|
||||
//инициализация стандартного веб сервера и веб сокетов
|
||||
// инициализация стандартного веб сервера и веб сокетов
|
||||
#ifdef STANDARD_WEB_SERVER
|
||||
standWebServerInit();
|
||||
#endif
|
||||
@@ -55,7 +55,7 @@ void setup() {
|
||||
// NTP
|
||||
ntpInit();
|
||||
|
||||
//инициализация mqtt
|
||||
// инициализация mqtt
|
||||
mqttInit();
|
||||
|
||||
// настраиваем i2c шину
|
||||
@@ -75,19 +75,19 @@ void setup() {
|
||||
SerialPrint("i", "i2c", F("i2c pins overriding done"));
|
||||
}
|
||||
|
||||
//настраиваем микроконтроллер
|
||||
// настраиваем микроконтроллер
|
||||
configure("/config.json");
|
||||
|
||||
//инициализация задач переодического выполнения
|
||||
// инициализация задач переодического выполнения
|
||||
periodicTasksInit();
|
||||
|
||||
//синхронизация списка устройств
|
||||
// синхронизация списка устройств
|
||||
addThisDeviceToList();
|
||||
|
||||
//запуск работы udp
|
||||
// запуск работы udp
|
||||
asyncUdpInit();
|
||||
|
||||
//подготавливаем сценарии
|
||||
// подготавливаем сценарии
|
||||
iotScen.loadScenario("/scenario.txt");
|
||||
|
||||
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
|
||||
@@ -122,9 +122,9 @@ void setup() {
|
||||
// IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"rel4\",\"val\":34,\"int\":30}"));
|
||||
// пример получения JSON всех Items
|
||||
// Serial.println(getParamsJson());
|
||||
//чтение одного параметра
|
||||
// чтение одного параметра
|
||||
// Serial.println(findIoTItem("t1")->getValue());
|
||||
//тест перебора пинов из расширения
|
||||
// тест перебора пинов из расширения
|
||||
// for (int i = 109; i < 112; i++) {
|
||||
// IoTgpio.pinMode(i, OUTPUT);
|
||||
// IoTgpio.digitalWrite(i, !IoTgpio.digitalRead(i));
|
||||
@@ -172,10 +172,10 @@ void loop() {
|
||||
// #endif
|
||||
}
|
||||
|
||||
//отправка json
|
||||
//#ifdef QUEUE_FROM_STR
|
||||
// if (sendJsonFiles) sendJsonFiles->loop();
|
||||
//#endif
|
||||
// отправка json
|
||||
// #ifdef QUEUE_FROM_STR
|
||||
// if (sendJsonFiles) sendJsonFiles->loop();
|
||||
// #endif
|
||||
|
||||
// if(millis()%2000==0){
|
||||
// //watch->settimeUnix(time(&iotTimeNow));
|
||||
|
||||
@@ -125,18 +125,26 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
|
||||
payloadStr += (char)payload[i];
|
||||
}
|
||||
|
||||
// распространяем принятое сообщение через хуки
|
||||
// генерация события прихода mqtt сообщения в модуле
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
(*it)->onMqttRecive(topicStr, payloadStr);
|
||||
}
|
||||
|
||||
if (payloadStr.startsWith("HELLO")) {
|
||||
SerialPrint("i", F("MQTT"), F("Full update"));
|
||||
publishWidgets();
|
||||
publishState();
|
||||
|
||||
//обращение к логированию из ядра
|
||||
//отправка данных графиков
|
||||
//публикация всех виджетов
|
||||
publishWidgets();
|
||||
|
||||
//публикация всех статус сообщений при подключении приложения и генерация события подключения приложения в модулях
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->iAmLocal) {
|
||||
publishStatusMqtt((*it)->getID(), (*it)->getValue());
|
||||
(*it)->onMqttWsAppConnectEvent();
|
||||
}
|
||||
}
|
||||
|
||||
//отправка данных графиков - данный код будет оптимизирован после завершения написания приложения с новыми графиками
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
|
||||
(*it)->setPublishDestination(TO_MQTT);
|
||||
@@ -182,14 +190,6 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
|
||||
generateOrder(id, payloadStr);
|
||||
SerialPrint("i", F("=>MQTT"), "Received direct order " + id + " " + payloadStr);
|
||||
}
|
||||
|
||||
// else if (topicStr.indexOf("info") != -1) {
|
||||
// if (topicStr.indexOf("scen") != -1) {
|
||||
// writeFile(String(DEVICE_SCENARIO_FILE), payloadStr);
|
||||
// loadScenario();
|
||||
// SerialPrint("i", F("=>MQTT"), F("Scenario received"));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
boolean publish(const String& topic, const String& data) {
|
||||
@@ -218,16 +218,6 @@ boolean publishChartMqtt(const String& topic, const String& data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean publishControl(String id, String topic, String state) {
|
||||
String path = mqttPrefix + "/" + id + "/" + topic + "/control";
|
||||
return mqtt.publish(path.c_str(), state.c_str(), false);
|
||||
}
|
||||
|
||||
boolean publishChart_test(const String& topic, const String& data) {
|
||||
String path = mqttRootDevice + "/" + topic + "/status";
|
||||
return mqtt.publish(path.c_str(), data.c_str(), false);
|
||||
}
|
||||
|
||||
boolean publishStatusMqtt(const String& topic, const String& data) {
|
||||
String path = mqttRootDevice + "/" + topic + "/status";
|
||||
String json = "{}";
|
||||
@@ -235,10 +225,8 @@ boolean publishStatusMqtt(const String& topic, const String& data) {
|
||||
return mqtt.publish(path.c_str(), json.c_str(), false);
|
||||
}
|
||||
|
||||
boolean publishAnyJsonKey(const String& topic, const String& key, const String& data) {
|
||||
boolean publishJsonMqtt(const String& topic, const String& json) {
|
||||
String path = mqttRootDevice + "/" + topic + "/status";
|
||||
String json = "{}";
|
||||
jsonWriteStr(json, key, data);
|
||||
return mqtt.publish(path.c_str(), json.c_str(), false);
|
||||
}
|
||||
|
||||
@@ -247,11 +235,6 @@ boolean publishEvent(const String& topic, const String& data) {
|
||||
return mqtt.publish(path.c_str(), data.c_str(), false);
|
||||
}
|
||||
|
||||
boolean publishInfo(const String& topic, const String& data) {
|
||||
String path = mqttRootDevice + "/" + topic + "/info";
|
||||
return mqtt.publish(path.c_str(), data.c_str(), false);
|
||||
}
|
||||
|
||||
void publishWidgets() {
|
||||
auto file = seekFile("layout.json");
|
||||
if (!file) {
|
||||
@@ -272,24 +255,6 @@ void publishWidgets() {
|
||||
file.close();
|
||||
}
|
||||
|
||||
void publishState() {
|
||||
String json = getParamsJson();
|
||||
SerialPrint("i", F("DATA"), json);
|
||||
json.replace("{", "");
|
||||
json.replace("}", "");
|
||||
json.replace("\"", "");
|
||||
json += ",";
|
||||
while (json.length() != 0) {
|
||||
String tmp = selectToMarker(json, ",");
|
||||
String topic = selectToMarker(tmp, ":");
|
||||
String state = deleteBeforeDelimiter(tmp, ":");
|
||||
if (topic != "" && state != "") {
|
||||
publishStatusMqtt(topic, state);
|
||||
}
|
||||
json = deleteBeforeDelimiter(json, ",");
|
||||
}
|
||||
}
|
||||
|
||||
bool publishChartFileToMqtt(String path, String id, int maxCount) {
|
||||
File configFile = FileFS.open(path, FILE_READ);
|
||||
if (!configFile) {
|
||||
@@ -310,7 +275,6 @@ void handleMqttStatus(bool send) {
|
||||
String stateStr = getStateStr(mqtt.state());
|
||||
// Serial.println(stateStr);
|
||||
jsonWriteStr_(errorsHeapJson, F("mqtt"), stateStr);
|
||||
|
||||
if (!send) sendStringToWs("errors", errorsHeapJson, -1);
|
||||
}
|
||||
|
||||
@@ -321,8 +285,6 @@ void handleMqttStatus(bool send, int state) {
|
||||
if (!send) sendStringToWs("errors", errorsHeapJson, -1);
|
||||
}
|
||||
|
||||
// log-20384820.txt
|
||||
|
||||
const String getStateStr(int e) {
|
||||
switch (e) {
|
||||
case -4: //Нет ответа от сервера
|
||||
|
||||
20
src/NTP.cpp
20
src/NTP.cpp
@@ -29,6 +29,7 @@ void ntpInit() {
|
||||
dateAndTime = deleteToMarkerLast(dateAndTime, ":");
|
||||
jsonWriteStr_(errorsHeapJson, F("timenow"), dateAndTime);
|
||||
SerialPrint("I", F("NTP"), "✔ " + dateAndTime);
|
||||
onDayChange();
|
||||
}
|
||||
_time_isTrust = true; // доверяем значению времени
|
||||
},
|
||||
@@ -41,6 +42,25 @@ void synchTime() {
|
||||
configTime(0, 0, "pool.ntp.org", "ru.pool.ntp.org", "pool.ntp.org");
|
||||
}
|
||||
|
||||
//событие смены даты
|
||||
bool onDayChange() {
|
||||
bool changed = false;
|
||||
String currentDate = getTodayDateDotFormated();
|
||||
if (!firstTimeInit) {
|
||||
if (prevDate != currentDate) {
|
||||
changed = true;
|
||||
SerialPrint("i", F("NTP"), F("Change day core event"));
|
||||
//установим новую дату во всех графиках системы
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
(*it)->setTodayDate();
|
||||
}
|
||||
}
|
||||
}
|
||||
firstTimeInit = false;
|
||||
prevDate = currentDate;
|
||||
return changed;
|
||||
}
|
||||
|
||||
unsigned long gmtTimeToLocal(unsigned long gmtTimestamp) {
|
||||
return gmtTimestamp + (jsonReadInt(settingsFlashJson, F("timezone")) * 60 * 60);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
|
||||
case WStype_TEXT: {
|
||||
bool endOfHeaderFound = false;
|
||||
size_t maxAllowedHeaderSize = 15; //максимальное количество символов заголовка
|
||||
size_t maxAllowedHeaderSize = 15; // максимальное количество символов заголовка
|
||||
size_t headerLenth = 0;
|
||||
String headerStr;
|
||||
for (size_t i = 0; i <= maxAllowedHeaderSize; i++) {
|
||||
@@ -54,32 +54,38 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// Страница веб интерфейса dashboard
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//отвечаем данными на запрос страницы
|
||||
// публикация всех виджетов
|
||||
if (headerStr == "/|") {
|
||||
sendFileToWsByFrames("/layout.json", "layout", "", num, WEB_SOCKETS_FRAME_SIZE);
|
||||
}
|
||||
|
||||
//отвечаем на запрос параметров
|
||||
if (headerStr == "/params|") {
|
||||
// публикация всех статус сообщений при подключении svelte приложения
|
||||
String params = "{}";
|
||||
// jsonWriteStr(params, "params_", ""); //метка для парсинга удалить
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getSubtype() != "Loging") {
|
||||
if ((*it)->iAmLocal) jsonWriteStr(params, (*it)->getID(), (*it)->getValue());
|
||||
if ((*it)->getSubtype() != "LogingDaily") {
|
||||
if ((*it)->iAmLocal) jsonWriteStr(params, (*it)->getID(), (*it)->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
sendStringToWs("params", params, num);
|
||||
|
||||
// генерация события подключения в модулях
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent();
|
||||
}
|
||||
}
|
||||
|
||||
//отвечаем на запрос графиков
|
||||
// отвечаем на запрос графиков
|
||||
if (headerStr == "/charts|") {
|
||||
//обращение к логированию из ядра
|
||||
//отправка данных графиков только в выбранный сокет
|
||||
// обращение к логированию из ядра
|
||||
// отправка данных графиков только в выбранный сокет
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
//сбрасываем даты графиков
|
||||
// if ((*it)->getID().endsWith("-date")) {
|
||||
// (*it)->setTodayDate();
|
||||
//}
|
||||
// сбрасываем даты графиков
|
||||
// if ((*it)->getID().endsWith("-date")) {
|
||||
// (*it)->setTodayDate();
|
||||
// }
|
||||
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
|
||||
(*it)->setPublishDestination(TO_WS, num);
|
||||
(*it)->publishValue();
|
||||
@@ -91,7 +97,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// Страница веб интерфейса configutation
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//отвечаем данными на запрос страницы
|
||||
// отвечаем данными на запрос страницы
|
||||
if (headerStr == "/config|") {
|
||||
sendFileToWsByFrames("/items.json", "itemsj", "", num, WEB_SOCKETS_FRAME_SIZE);
|
||||
sendFileToWsByFrames("/widgets.json", "widget", "", num, WEB_SOCKETS_FRAME_SIZE);
|
||||
@@ -100,7 +106,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
sendStringToWs("settin", settingsFlashJson, num);
|
||||
}
|
||||
|
||||
//обработка кнопки сохранить
|
||||
// обработка кнопки сохранить
|
||||
if (headerStr == "/gifnoc|") {
|
||||
writeFileUint8tByFrames("config.json", payload, length, headerLenth, 256);
|
||||
}
|
||||
@@ -120,7 +126,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// Страница веб интерфейса connection
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//отвечаем данными на запрос страницы
|
||||
// отвечаем данными на запрос страницы
|
||||
if (headerStr == "/connection|") {
|
||||
sendStringToWs("settin", settingsFlashJson, num);
|
||||
sendStringToWs("ssidli", ssidListHeapJson, num);
|
||||
@@ -129,7 +135,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// RouterFind(jsonReadStr(settingsFlashJson, F("routerssid")));
|
||||
}
|
||||
|
||||
//обработка кнопки сохранить настройки wifi
|
||||
// обработка кнопки сохранить настройки wifi
|
||||
if (headerStr == "/sgnittes|") {
|
||||
writeUint8tToString(payload, length, headerLenth, settingsFlashJson);
|
||||
writeFileUint8tByFrames("settings.json", payload, length, headerLenth, 256);
|
||||
@@ -137,16 +143,16 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
addThisDeviceToList();
|
||||
}
|
||||
|
||||
//обработка кнопки сохранить настройки mqtt
|
||||
// обработка кнопки сохранить настройки mqtt
|
||||
if (headerStr == "/mqtt|") {
|
||||
sendStringToWs("settin", settingsFlashJson, num); //отправляем в ответ новые полученные настройки
|
||||
handleMqttStatus(false, 8); //меняем статус на неопределенный
|
||||
mqttReconnect(); //начинаем переподключение
|
||||
sendStringToWs("errors", errorsHeapJson, num); //отправляем что статус неопределен
|
||||
sendStringToWs("settin", settingsFlashJson, num); // отправляем в ответ новые полученные настройки
|
||||
handleMqttStatus(false, 8); // меняем статус на неопределенный
|
||||
mqttReconnect(); // начинаем переподключение
|
||||
sendStringToWs("errors", errorsHeapJson, num); // отправляем что статус неопределен
|
||||
sendStringToWs("ssidli", ssidListHeapJson, num);
|
||||
}
|
||||
|
||||
//запуск асинхронного сканирования wifi сетей при нажатии выпадающего списка
|
||||
// запуск асинхронного сканирования wifi сетей при нажатии выпадающего списка
|
||||
if (headerStr == "/scan|") {
|
||||
RouterFind(jsonReadStr(settingsFlashJson, F("routerssid")));
|
||||
sendStringToWs("ssidli", ssidListHeapJson, num);
|
||||
@@ -156,7 +162,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// Страница веб интерфейса list
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//отвечаем данными на запрос страницы
|
||||
// отвечаем данными на запрос страницы
|
||||
if (headerStr == "/list|") {
|
||||
sendStringToWs("devlis", devListHeapJson, num);
|
||||
}
|
||||
@@ -165,7 +171,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// Страница веб интерфейса system
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//отвечаем данными на запрос страницы
|
||||
// отвечаем данными на запрос страницы
|
||||
if (headerStr == "/system|") {
|
||||
sendStringToWs("errors", errorsHeapJson, num);
|
||||
sendStringToWs("settin", settingsFlashJson, num);
|
||||
@@ -189,27 +195,27 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// отдельные команды веб интерфейса
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
//переписать любое поле в errors json
|
||||
// переписать любое поле в errors json
|
||||
if (headerStr == "/rorre|") {
|
||||
writeUint8tValueToJsonString(payload, length, headerLenth, errorsHeapJson);
|
||||
}
|
||||
|
||||
//команда перезагрузки esp
|
||||
// команда перезагрузки esp
|
||||
if (headerStr == "/reboot|") {
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
//команда очистки всех логов esp
|
||||
// команда очистки всех логов esp
|
||||
if (headerStr == "/clean|") {
|
||||
cleanLogs();
|
||||
}
|
||||
|
||||
//команда обновления прошивки esp
|
||||
// команда обновления прошивки esp
|
||||
if (headerStr == "/update|") {
|
||||
upgrade_firmware(3);
|
||||
}
|
||||
|
||||
//Прием команд control c dashboard
|
||||
// Прием команд control c dashboard
|
||||
if (headerStr == "/control|") {
|
||||
String msg;
|
||||
writeUint8tToString(payload, length, headerLenth, msg);
|
||||
@@ -223,6 +229,25 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
standWebSocket.sendTXT(num, "/tstr|");
|
||||
}
|
||||
|
||||
// получаем команду посланную из модуля
|
||||
if (headerStr == "/order|") {
|
||||
String json;
|
||||
writeUint8tToString(payload, length, headerLenth, json);
|
||||
|
||||
String id, key, value;
|
||||
jsonRead(json, "id", id);
|
||||
jsonRead(json, "key", key);
|
||||
jsonRead(json, "value", value);
|
||||
|
||||
SerialPrint("i", F("=>WS"), "Msg from module, id: " + id);
|
||||
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getID() == id) {
|
||||
(*it)->onModuleOrder(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case WStype_BIN: {
|
||||
@@ -261,7 +286,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
}
|
||||
}
|
||||
|
||||
//публикация статус сообщений (недостаток в том что делаем бродкаст всем клиентам поднятым в свелте!!!)
|
||||
// публикация статус сообщений в ws (недостаток в том что делаем бродкаст всем клиентам поднятым в свелте!!!)
|
||||
void publishStatusWs(const String& topic, const String& data) {
|
||||
String path = mqttRootDevice + "/" + topic;
|
||||
String json = "{}";
|
||||
@@ -270,11 +295,15 @@ void publishStatusWs(const String& topic, const String& data) {
|
||||
sendStringToWs("status", json, -1);
|
||||
}
|
||||
|
||||
void publishChartWs(int num, String& path) {
|
||||
// sendFileToWs(path, num, 1000);
|
||||
// публикация дополнительных json сообщений в ws
|
||||
void publishJsonWs(const String& topic, String& json) {
|
||||
String path = mqttRootDevice + "/" + topic;
|
||||
jsonWriteStr(json, "topic", path);
|
||||
// TO DO отправка полей в веб
|
||||
// sendStringToWs("status", json, -1);
|
||||
}
|
||||
|
||||
//данные которые мы отправляем в сокеты переодически
|
||||
// данные которые мы отправляем в сокеты переодически
|
||||
void periodicWsSend() {
|
||||
sendStringToWs("ssidli", ssidListHeapJson, -1);
|
||||
sendStringToWs("errors", errorsHeapJson, -1);
|
||||
@@ -375,7 +404,6 @@ void sendStringToWs(const String& header, String& payload, int client_id) {
|
||||
|
||||
String msg = header + "|0012|" + payload;
|
||||
size_t totalSize = msg.length();
|
||||
// Serial.println("Send string '" + header + "', str size: " + String(totalSize));
|
||||
|
||||
char dataArray[totalSize];
|
||||
msg.toCharArray(dataArray, totalSize + 1);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "ESPConfiguration.h"
|
||||
#include "EventsAndOrders.h"
|
||||
|
||||
//получение параметров в экземпляр класса
|
||||
IoTItem::IoTItem(const String& parameters) {
|
||||
jsonRead(parameters, F("int"), _interval, false);
|
||||
if (_interval <= 0) enableDoByInt = false;
|
||||
@@ -33,11 +32,10 @@ IoTItem::IoTItem(const String& parameters) {
|
||||
setValue(valAsStr, false);
|
||||
|
||||
jsonRead(parameters, F("needSave"), _needSave, false);
|
||||
if (_needSave && jsonRead(valuesFlashJson, _id, valAsStr, false)) // пробуем достать из сохранения значение элемента, если указано, что нужно сохранять
|
||||
if (_needSave && jsonRead(valuesFlashJson, _id, valAsStr, false)) // пробуем достать из сохранения значение элемента, если указано, что нужно сохранять
|
||||
setValue(valAsStr, false);
|
||||
}
|
||||
|
||||
//луп выполняющий переодическое дерганье
|
||||
void IoTItem::loop() {
|
||||
if (enableDoByInt) {
|
||||
currentMillis = millis();
|
||||
@@ -49,7 +47,6 @@ void IoTItem::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
//получить
|
||||
String IoTItem::getValue() {
|
||||
if (value.isDecimal) {
|
||||
return getRoundValue();
|
||||
@@ -59,12 +56,11 @@ String IoTItem::getValue() {
|
||||
|
||||
long IoTItem::getInterval() { return _interval; }
|
||||
|
||||
bool IoTItem::isGlobal() { return _global;}
|
||||
bool IoTItem::isGlobal() { return _global; }
|
||||
|
||||
//определяем тип прилетевшей величины
|
||||
void IoTItem::setValue(const String& valStr, bool genEvent) {
|
||||
value.isDecimal = isDigitDotCommaStr(valStr);
|
||||
|
||||
|
||||
if (value.isDecimal) {
|
||||
value.valD = valStr.toFloat();
|
||||
} else {
|
||||
@@ -73,10 +69,9 @@ void IoTItem::setValue(const String& valStr, bool genEvent) {
|
||||
setValue(value, genEvent);
|
||||
}
|
||||
|
||||
//
|
||||
void IoTItem::setValue(const IoTValue& Value, bool genEvent) {
|
||||
value = Value;
|
||||
|
||||
|
||||
if (value.isDecimal) {
|
||||
regEvent(value.valD, "", false, genEvent);
|
||||
} else {
|
||||
@@ -84,7 +79,14 @@ void IoTItem::setValue(const IoTValue& Value, bool genEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
//когда событие случилось
|
||||
// метод отправки из модуля дополнительных json полей виджета в приложение и веб интерфейс,
|
||||
// необходимый для изменения виджетов "на лету" из модуля
|
||||
void IoTItem::sendSubWidgetsValues(String& id, String& json) {
|
||||
publishJsonMqtt(id, json);
|
||||
publishJsonWs(id, json);
|
||||
}
|
||||
|
||||
// когда событие случилось
|
||||
void IoTItem::regEvent(const String& value, const String& consoleInfo, bool error, bool genEvent) {
|
||||
if (_needSave) {
|
||||
jsonWriteStr_(valuesFlashJson, _id, value);
|
||||
@@ -92,26 +94,25 @@ void IoTItem::regEvent(const String& value, const String& consoleInfo, bool erro
|
||||
}
|
||||
publishStatusMqtt(_id, value);
|
||||
publishStatusWs(_id, value);
|
||||
//SerialPrint("i", "Sensor", consoleInfo + " '" + _id + "' data: " + value + "'");
|
||||
|
||||
// SerialPrint("i", "Sensor", consoleInfo + " '" + _id + "' data: " + value + "'");
|
||||
|
||||
if (genEvent) {
|
||||
generateEvent(_id, value);
|
||||
|
||||
// распространяем событие через хуки
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
(*it)->onRegEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
//отправка события другим устройствам в сети если не было ошибки==============================
|
||||
// отправка события другим устройствам в сети если не было ошибки
|
||||
if (jsonReadBool(settingsFlashJson, "mqttin") && _global && !error) {
|
||||
String json = "{}";
|
||||
jsonWriteStr_(json, "id", _id);
|
||||
jsonWriteStr_(json, "val", value);
|
||||
jsonWriteInt_(json, "int", _interval/1000);
|
||||
jsonWriteInt_(json, "int", _interval / 1000);
|
||||
publishEvent(_id, json);
|
||||
SerialPrint("i", F("<=MQTT"), "Broadcast event: " + json);
|
||||
}
|
||||
//========================================================================
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ String IoTItem::getRoundValue() {
|
||||
if (_round >= 0 && _round <= 6) {
|
||||
int sot = _round ? pow(10, (int)_round) : 1;
|
||||
value.valD = round(value.valD * sot) / sot;
|
||||
|
||||
|
||||
char buf[15];
|
||||
sprintf(buf, ("%1." + (String)_round + "f").c_str(), value.valD);
|
||||
value.valS = (String)buf;
|
||||
@@ -155,7 +156,7 @@ void IoTItem::getNetEvent(String& event) {
|
||||
event = "{}";
|
||||
jsonWriteStr_(event, "id", _id);
|
||||
jsonWriteStr_(event, "val", getValue());
|
||||
jsonWriteInt_(event, "int", _interval/1000);
|
||||
jsonWriteInt_(event, "int", _interval / 1000);
|
||||
}
|
||||
|
||||
void IoTItem::setIntFromNet(int interval) {
|
||||
@@ -174,18 +175,20 @@ void IoTItem::checkIntFromNet() {
|
||||
}
|
||||
}
|
||||
|
||||
// хуки для системных событий (должны начинаться с "on")
|
||||
void IoTItem::onRegEvent(IoTItem* item) {}
|
||||
|
||||
void IoTItem::onMqttRecive(String& topic, String& msg) {}
|
||||
void IoTItem::onMqttWsAppConnectEvent() {}
|
||||
void IoTItem::onModuleOrder(String& key, String& value) {}
|
||||
|
||||
// делаем доступным модулям отправку сообщений в телеграм
|
||||
void IoTItem::sendTelegramMsg(bool often, String msg) {}
|
||||
|
||||
// методы для графиков (будет упрощено)
|
||||
void IoTItem::publishValue() {}
|
||||
|
||||
void IoTItem::clearValue() {}
|
||||
|
||||
void IoTItem::setPublishDestination(int publishType, int wsNum){};
|
||||
|
||||
void IoTItem::clearHistory() {}
|
||||
|
||||
void IoTItem::setTodayDate() {}
|
||||
|
||||
String IoTItem::getID() {
|
||||
@@ -200,8 +203,7 @@ IoTGpio* IoTItem::getGpioDriver() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//сетевое общение====================================================================================================================================
|
||||
// сетевое общение====================================================================================================================================
|
||||
|
||||
// externalVariable::externalVariable(const String& parameters) : IoTItem(parameters) {
|
||||
// prevMillis = millis(); // запоминаем текущее значение таймера для выполения doByInterval после int сек
|
||||
@@ -257,14 +259,14 @@ IoTItem* createItemFromNet(const String& itemId, const String& value, int interv
|
||||
jsonStr += "\",\"int\":";
|
||||
jsonStr += interval;
|
||||
jsonStr += "}";
|
||||
|
||||
|
||||
return createItemFromNet(jsonStr);
|
||||
}
|
||||
|
||||
// создаем временную копию элемента из сети на основе события
|
||||
IoTItem* createItemFromNet(const String& msgFromNet) {
|
||||
IoTItem *tmpp = new IoTItem(msgFromNet);
|
||||
if (tmpp->getInterval()) tmpp->setIntFromNet(tmpp->getInterval()/1000 + 5);
|
||||
IoTItem* tmpp = new IoTItem(msgFromNet);
|
||||
if (tmpp->getInterval()) tmpp->setIntFromNet(tmpp->getInterval() / 1000 + 5);
|
||||
tmpp->iAmLocal = false;
|
||||
IoTItems.push_back(tmpp);
|
||||
generateEvent(tmpp->getID(), tmpp->getValue());
|
||||
@@ -272,7 +274,7 @@ IoTItem* createItemFromNet(const String& msgFromNet) {
|
||||
}
|
||||
|
||||
void analyzeMsgFromNet(const String& msg, String altId) {
|
||||
if (!jsonRead(msg, F("id"), altId, altId == "") && altId == "") return; // ничего не предпринимаем, если ошибка и altId = "", вообще данная конструкция нужна для совместимости с форматом данных 3 версией
|
||||
if (!jsonRead(msg, F("id"), altId, altId == "") && altId == "") return; // ничего не предпринимаем, если ошибка и altId = "", вообще данная конструкция нужна для совместимости с форматом данных 3 версией
|
||||
IoTItem* itemExist = findIoTItem(altId);
|
||||
if (itemExist) {
|
||||
String valAsStr = msg;
|
||||
@@ -280,9 +282,9 @@ void analyzeMsgFromNet(const String& msg, String altId) {
|
||||
long interval = 0;
|
||||
jsonRead(msg, F("int"), interval, false);
|
||||
|
||||
itemExist->setInterval(interval); // устанавливаем такой же интервал как на источнике события
|
||||
itemExist->setValue(valAsStr, false); // только регистрируем изменения в интерфейсе без создания цикла сетевых событий
|
||||
if (interval) itemExist->setIntFromNet(interval+5); // если пришедший интервал =0, значит не нужно контролировать доверие, иначе даем фору в 5 сек
|
||||
itemExist->setInterval(interval); // устанавливаем такой же интервал как на источнике события
|
||||
itemExist->setValue(valAsStr, false); // только регистрируем изменения в интерфейсе без создания цикла сетевых событий
|
||||
if (interval) itemExist->setIntFromNet(interval + 5); // если пришедший интервал =0, значит не нужно контролировать доверие, иначе даем фору в 5 сек
|
||||
generateEvent(altId, valAsStr);
|
||||
} else {
|
||||
// временно зафиксируем данные в базе, если локально элемент отсутствует
|
||||
|
||||
429
src/modules/exec/MySensors/MySensorsGate.cpp
Normal file
429
src/modules/exec/MySensors/MySensorsGate.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
#include "Arduino.h"
|
||||
#include "MySensorsGate.h"
|
||||
|
||||
#ifdef MYSENSORS
|
||||
// callback библиотеки mysensors
|
||||
void receive(const MyMessage& message) {
|
||||
String inMsg = String(message.getSender()) + "," + // node-id
|
||||
String(message.getSensor()) + "," + // child-sensor-id
|
||||
String(message.getType()) + "," + // type of var
|
||||
String(message.getCommand()) + "," + // command
|
||||
parseToString(message) + ";"; // value
|
||||
|
||||
// Serial.println("=>" + inMsg);
|
||||
|
||||
mysensorBuf += inMsg;
|
||||
}
|
||||
|
||||
String parseToString(const MyMessage& message) {
|
||||
String value = "error";
|
||||
switch (message.getPayloadType()) {
|
||||
case 0: // Payload type is string
|
||||
value = message.getString();
|
||||
return value;
|
||||
case 1: // Payload type is byte
|
||||
value = String(message.getByte());
|
||||
return value;
|
||||
case 2: // Payload type is INT16
|
||||
value = String(message.getInt());
|
||||
return value;
|
||||
case 3: // Payload type is UINT16
|
||||
value = String(message.getUInt());
|
||||
return value;
|
||||
case 4: // Payload type is INT32
|
||||
value = String(message.getInt());
|
||||
return value;
|
||||
case 5: // Payload type is UINT32
|
||||
value = String(message.getUInt());
|
||||
return value;
|
||||
case 6: // Payload type is binary
|
||||
value = String(message.getBool());
|
||||
return value;
|
||||
case 7: // Payload type is float32
|
||||
value = String(message.getFloat());
|
||||
return value;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
class MySensorsGate : public IoTItem {
|
||||
private:
|
||||
public:
|
||||
MySensorsGate(String parameters) : IoTItem(parameters) {
|
||||
SerialPrint("i", "MySensors", "Gate initialized");
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
loopMySensorsExecute();
|
||||
}
|
||||
|
||||
~MySensorsGate(){};
|
||||
|
||||
void loopMySensorsExecute() {
|
||||
if (mysensorBuf.length()) {
|
||||
String tmp = selectToMarker(mysensorBuf, ";");
|
||||
|
||||
String nodeId = selectFromMarkerToMarker(tmp, ",", 0); // node-id
|
||||
String childSensorId = selectFromMarkerToMarker(tmp, ",", 1); // child-sensor-id
|
||||
String type = selectFromMarkerToMarker(tmp, ",", 2); // type of var
|
||||
String command = selectFromMarkerToMarker(tmp, ",", 3); // command
|
||||
String value = selectFromMarkerToMarker(tmp, ",", 4); // value
|
||||
|
||||
static bool presentBeenStarted = false;
|
||||
|
||||
String ID = "n" + nodeId + "s" + childSensorId;
|
||||
static String infoJson = "{}";
|
||||
|
||||
if (childSensorId == "255") {
|
||||
if (command == "3") { // это особое внутреннее сообщение
|
||||
if (type == "11") { // название ноды
|
||||
SerialPrint("i", "MySensors", "===================== " + value + " =====================");
|
||||
}
|
||||
if (type == "12") { // версия ноды
|
||||
SerialPrint("i", "MySensors", "Node version: " + value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (command == "0") { // это презентация
|
||||
presentBeenStarted = true;
|
||||
int num;
|
||||
String widget;
|
||||
String descr;
|
||||
sensorType(type.toInt(), num, widget, descr);
|
||||
|
||||
descr.replace("#", " ");
|
||||
SerialPrint("i", "MySensors", "Presentation: " + ID + ": " + descr);
|
||||
}
|
||||
if (command == "1") { // это данные
|
||||
if (value != "") {
|
||||
if (presentBeenStarted) {
|
||||
presentBeenStarted = false;
|
||||
SerialPrint("i", "MySensors", "===================== " + nodeId + " =====================");
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getID() == ID) {
|
||||
found = true;
|
||||
(*it)->setValue(value, true);
|
||||
}
|
||||
}
|
||||
|
||||
SerialPrint("i", "MySensors", "node: " + nodeId + ", sensor: " + childSensorId + ", command: " + command + ", type: " + type + ", val: " + value + ", found: " + String(found));
|
||||
}
|
||||
}
|
||||
if (command == "2") { // это запрос значения переменной
|
||||
SerialPrint("i", "MySensors", "Request a variable value");
|
||||
}
|
||||
}
|
||||
|
||||
mysensorBuf = deleteBeforeDelimiter(mysensorBuf, ";");
|
||||
}
|
||||
}
|
||||
|
||||
void sensorType(int index, int& num, String& widget, String& descr) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
descr = F("Door#and#window#sensors");
|
||||
widget = F("alarm");
|
||||
num = 1;
|
||||
break;
|
||||
case 1:
|
||||
descr = F("Motion#sensors");
|
||||
widget = F("alarm");
|
||||
num = 1;
|
||||
break;
|
||||
case 2:
|
||||
descr = F("Smoke#sensor");
|
||||
widget = F("fillgauge");
|
||||
num = 1;
|
||||
break;
|
||||
case 3:
|
||||
descr = F("Binary#device#(on/off)");
|
||||
widget = F("toggleBtn");
|
||||
num = 2;
|
||||
break;
|
||||
case 4:
|
||||
descr = F("Dimmable#device");
|
||||
// to do
|
||||
// widget = F("range");
|
||||
// num = 2;
|
||||
break;
|
||||
case 5:
|
||||
descr = F("Window#covers#or#shades");
|
||||
// to do
|
||||
// widget = F("range");
|
||||
// num = 2;
|
||||
break;
|
||||
case 6:
|
||||
descr = F("Temperature#sensor");
|
||||
widget = F("anydataTemp");
|
||||
num = 1;
|
||||
break;
|
||||
case 7:
|
||||
descr = F("Humidity#sensor");
|
||||
widget = F("anydataHum");
|
||||
num = 1;
|
||||
break;
|
||||
case 8:
|
||||
descr = F("Pressure#sensor");
|
||||
widget = F("anydataPress");
|
||||
num = 1;
|
||||
break;
|
||||
case 9:
|
||||
descr = F("Wind#sensor");
|
||||
widget = F("anydataTime");
|
||||
num = 1;
|
||||
break;
|
||||
case 10:
|
||||
descr = F("Rain#sensor");
|
||||
widget = F("anydataTime");
|
||||
num = 1;
|
||||
break;
|
||||
case 11:
|
||||
descr = F("UV#sensor");
|
||||
widget = F("anydataTime");
|
||||
num = 1;
|
||||
break;
|
||||
case 12:
|
||||
descr = F("Weight#sensor");
|
||||
widget = F("anydataTime");
|
||||
num = 1;
|
||||
break;
|
||||
case 13:
|
||||
descr = F("Power#measuring#device");
|
||||
widget = F("anydataWtt");
|
||||
num = 1;
|
||||
break;
|
||||
case 14:
|
||||
descr = F("Heater#device");
|
||||
widget = F("anydataTemp");
|
||||
num = 1;
|
||||
break;
|
||||
case 15:
|
||||
descr = F("Distance#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 16:
|
||||
descr = F("Light#sensor");
|
||||
widget = F("anydataTime");
|
||||
num = 1;
|
||||
break;
|
||||
case 17:
|
||||
descr = F("Arduino#node#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 18:
|
||||
descr = F("Arduino#repeating#node#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 19:
|
||||
descr = F("Lock#device");
|
||||
widget = F("toggleBtn");
|
||||
num = 2;
|
||||
break;
|
||||
case 20:
|
||||
descr = F("Ir#sender/receiver#device");
|
||||
widget = F("toggleBtn");
|
||||
num = 2;
|
||||
break;
|
||||
case 21:
|
||||
descr = F("Water#meter");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 22:
|
||||
descr = F("Air#quality#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 23:
|
||||
descr = F("Custom#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 24:
|
||||
descr = F("Dust#level#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 25:
|
||||
descr = F("Scene#controller#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 26:
|
||||
descr = F("RGB#light");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 27:
|
||||
descr = F("RGBW#light#(with#separate#white#component)");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 28:
|
||||
descr = F("Color#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 29:
|
||||
descr = F("Thermostat/HVAC#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 30:
|
||||
descr = F("Multimeter#device");
|
||||
widget = F("anydataVlt");
|
||||
num = 1;
|
||||
break;
|
||||
case 31:
|
||||
descr = F("Sprinkler#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 32:
|
||||
descr = F("Water#leak#sensor");
|
||||
widget = F("alarm");
|
||||
num = 1;
|
||||
break;
|
||||
case 33:
|
||||
descr = F("Sound#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 34:
|
||||
descr = F("Vibration#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 35:
|
||||
descr = F("Moisture#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 36:
|
||||
descr = F("LCD#text#device");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 37:
|
||||
descr = F("Gas#meter");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 38:
|
||||
descr = F("GPS#Sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
case 39:
|
||||
descr = F("Water#quality#sensor");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
default:
|
||||
descr = F("Unknown");
|
||||
widget = F("anydata");
|
||||
num = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MySensorsNode : public IoTItem {
|
||||
private:
|
||||
String id = "";
|
||||
int orange = 0;
|
||||
int red = 0;
|
||||
int offline = 0;
|
||||
int _minutesPassed = 0;
|
||||
String json = "{}";
|
||||
bool dataFromNode = false;
|
||||
|
||||
public:
|
||||
MySensorsNode(String parameters) : IoTItem(parameters) {
|
||||
jsonRead(parameters, F("id"), id);
|
||||
|
||||
jsonRead(parameters, F("orange"), orange);
|
||||
jsonRead(parameters, F("red"), red);
|
||||
jsonRead(parameters, F("offline"), offline);
|
||||
|
||||
dataFromNode = false;
|
||||
SerialPrint("i", "MySensors", "Node initialized");
|
||||
}
|
||||
|
||||
void setValue(const IoTValue& Value, bool genEvent = true) {
|
||||
value = Value;
|
||||
regEvent(value.valD, "MySensorsNode", false, genEvent);
|
||||
_minutesPassed = 0;
|
||||
prevMillis = millis();
|
||||
dataFromNode = true;
|
||||
setNewWidgetAttributes();
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
_minutesPassed++;
|
||||
setNewWidgetAttributes();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
currentMillis = millis();
|
||||
difference = currentMillis - prevMillis;
|
||||
if (difference > 60000) {
|
||||
prevMillis = millis();
|
||||
this->doByInterval();
|
||||
}
|
||||
}
|
||||
|
||||
// событие когда пользователь подключается приложением или веб интерфейсом к усройству
|
||||
void onMqttWsAppConnectEvent() {
|
||||
setNewWidgetAttributes();
|
||||
}
|
||||
|
||||
void setNewWidgetAttributes() {
|
||||
if (dataFromNode) {
|
||||
jsonWriteStr(json, F("info"), prettyMinutsTimeout(_minutesPassed));
|
||||
if (orange != 0 && red != 0 && offline != 0) {
|
||||
if (_minutesPassed < orange) {
|
||||
jsonWriteStr(json, F("color"), "");
|
||||
}
|
||||
if (_minutesPassed >= orange && _minutesPassed < red) {
|
||||
jsonWriteStr(json, F("color"), F("orange")); // сделаем виджет оранжевым
|
||||
}
|
||||
if (_minutesPassed >= red && _minutesPassed < offline) {
|
||||
jsonWriteStr(json, F("color"), F("red")); // сделаем виджет красным
|
||||
}
|
||||
if (_minutesPassed >= offline) {
|
||||
jsonWriteStr(json, F("info"), F("offline"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
jsonWriteStr(json, F("info"), F("awaiting"));
|
||||
}
|
||||
sendSubWidgetsValues(id, json);
|
||||
}
|
||||
|
||||
~MySensorsNode(){};
|
||||
};
|
||||
|
||||
void* getAPI_MySensorsGate(String subtype, String param) {
|
||||
if (subtype == F("MySensorsGate")) {
|
||||
return new MySensorsGate(param);
|
||||
} else if (subtype == F("MySensorsNode")) {
|
||||
return new MySensorsNode(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
54
src/modules/exec/MySensors/MySensorsGate.h
Normal file
54
src/modules/exec/MySensors/MySensorsGate.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "Const.h"
|
||||
#ifdef MYSENSORS
|
||||
|
||||
/*
|
||||
* DESCRIPTION
|
||||
* The ESP32 gateway sends data received from sensors to the WiFi link.
|
||||
* The gateway also accepts input on ethernet interface, which is then sent out to the radio network.
|
||||
* ----------- PINOUT --------------
|
||||
* | IO | RF24 | RFM69 | RFM95 |
|
||||
|------|------|-------|-------|
|
||||
| MOSI | 23 | 23 | 23 |
|
||||
| MISO | 19 | 19 | 19 |
|
||||
| SCK | 18 | 18 | 18 |
|
||||
| CSN | 5 | 5 | 5 |
|
||||
| CE | 17 | - | - |
|
||||
| RST | - | 17 | 17 |
|
||||
| IRQ | 16* | 16 | 16 |
|
||||
*/
|
||||
|
||||
// Enable debug prints to serial monitor
|
||||
//#define MY_DEBUG
|
||||
|
||||
//#define MY_RF24_CE_PIN 26 // Двигать пин CE на D4 чтобы освободить I2C
|
||||
//#define MY_RF24_CS_PIN 9
|
||||
|
||||
// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h
|
||||
#define MY_BAUD_RATE 115200
|
||||
|
||||
// Enables and select radio type (if attached)
|
||||
#define MY_RADIO_RF24
|
||||
//#define MY_RADIO_RFM69
|
||||
//#define MY_RADIO_RFM95
|
||||
|
||||
//#define MY_RF24_DATARATE RF24_1MBPS // Для платы KeyWish скорость 1 мегабит
|
||||
|
||||
// How many clients should be able to connect to this gateway (default 1)
|
||||
#define MY_GATEWAY_MAX_CLIENTS 10
|
||||
|
||||
// Set LOW transmit power level as default, if you have an amplified NRF-module and
|
||||
// power your radio separately with a good regulator you can turn up PA level.
|
||||
#define MY_RF24_PA_LEVEL RF24_PA_MAX
|
||||
|
||||
// используем гейт в режиме serial хотя нам этот режим не нужен, поэтому в библиотеки отключаем MY_SERIALDEVICE.print
|
||||
// в файле MyGatewayTransportSerial.cpp в строчке 35
|
||||
#define MY_GATEWAY_SERIAL
|
||||
|
||||
//#define CHILD_ID 1
|
||||
|
||||
#include <MySensors.h>
|
||||
|
||||
extern String parseToString(const MyMessage& message);
|
||||
|
||||
#endif
|
||||
54
src/modules/exec/MySensors/modinfo.json
Normal file
54
src/modules/exec/MySensors/modinfo.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"menuSection": "Исполнительные устройства",
|
||||
"configItem": [
|
||||
{
|
||||
"global": 0,
|
||||
"name": "MySensorsGate",
|
||||
"type": "Reading",
|
||||
"subtype": "MySensorsGate",
|
||||
"id": "gt",
|
||||
"widget": "nil",
|
||||
"page": "",
|
||||
"descr": ""
|
||||
},
|
||||
{
|
||||
"global": 0,
|
||||
"name": "MySensorsNode",
|
||||
"type": "Reading",
|
||||
"subtype": "MySensorsNode",
|
||||
"id": "n",
|
||||
"widget": "anydataTmp",
|
||||
"page": "MySensors",
|
||||
"descr": "Температура",
|
||||
"orange": 60,
|
||||
"red": 120,
|
||||
"offline": 180,
|
||||
"round": 1
|
||||
}
|
||||
],
|
||||
"about": {
|
||||
"authorName": "Dmitry Borisenko",
|
||||
"authorContact": "https://t.me/Dmitry_Borisenko",
|
||||
"authorGit": "https://github.com/DmitryBorisenko33",
|
||||
"specialThanks": "",
|
||||
"moduleName": "MySensorsGate",
|
||||
"moduleVersion": "1.0",
|
||||
"usedRam": {
|
||||
"esp32_4mb": 15,
|
||||
"esp8266_4mb": 0
|
||||
},
|
||||
"title": "Гейт MySensors",
|
||||
"moduleDesc": "Устройство состоит из esp32 и подключенному к нему радиомодулю NRF24L01. Вместе в связке они образуют гейт, способный принимать данные датчиков. Датчики способны работать до нескольких лет на батарейках. Датчики делаются на базе nrf52832 от holyiot. Батарейки подключаются напрямик к nrf52832",
|
||||
"retInfo": "",
|
||||
"propInfo": {
|
||||
"id": "Для настройки следует выбрать один раз MySensorsGate и выбрать сколько необходимо раз MySensorsNode. Вместо ID нужно указать например - n100s1. Это значит что мы будем получать данные с ноды 100 и с сенсора этой ноды под номером 1",
|
||||
"orange": "количество минут после которого окрасить виджет в оранжевый цвет",
|
||||
"red": "количество минут после которого окрасить виджет в красный цвет",
|
||||
"offline": "количество минут после которого отобразить что устройство offline, если все три orange red и offline поставить в ноль - то функция окраски выключится"
|
||||
}
|
||||
},
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,19 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
class TelegramLT : public IoTItem
|
||||
{
|
||||
|
||||
public:
|
||||
class TelegramLT : public IoTItem {
|
||||
public:
|
||||
String _prevMsg = "";
|
||||
String _token;
|
||||
String _chatID;
|
||||
|
||||
TelegramLT(String parameters) : IoTItem(parameters)
|
||||
{
|
||||
TelegramLT(String parameters) : IoTItem(parameters) {
|
||||
jsonRead(parameters, "token", _token);
|
||||
jsonRead(parameters, "chatID", _chatID);
|
||||
}
|
||||
|
||||
void sendTelegramMsg(bool often, String msg)
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED && (often || !often && _prevMsg != msg))
|
||||
{
|
||||
void sendTelegramMsg(bool often, String msg) {
|
||||
if (WiFi.status() == WL_CONNECTED && (often || !often && _prevMsg != msg)) {
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, "http://live-control.com/iotm/telegram.php");
|
||||
@@ -29,14 +24,11 @@ public:
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + _chatID + ", msg: " + msg);
|
||||
SerialPrint("->", F("Telegram"), "chat ID: " + _chatID + ", server: " + httpResponseCode);
|
||||
|
||||
if (!strstr(payload.c_str(), "{\"ok\":true"))
|
||||
{
|
||||
if (!strstr(payload.c_str(), "{\"ok\":true")) {
|
||||
value.valD = 0;
|
||||
Serial.printf("Telegram error, msg from server: %s\n", payload.c_str());
|
||||
regEvent(value.valD, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
value.valD = 1;
|
||||
regEvent(value.valD, payload);
|
||||
}
|
||||
@@ -45,27 +37,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m)
|
||||
{
|
||||
if (param.size() == 1)
|
||||
{
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (param.size() == 1) {
|
||||
String strTmp;
|
||||
if (param[0].isDecimal && param[0].valS == "")
|
||||
strTmp = param[0].valD;
|
||||
else
|
||||
strTmp = param[0].valS;
|
||||
|
||||
if (command == "sendMsg")
|
||||
{
|
||||
if (param.size())
|
||||
{
|
||||
if (command == "sendMsg") {
|
||||
if (param.size()) {
|
||||
sendTelegramMsg(false, strTmp);
|
||||
}
|
||||
}
|
||||
else if (command == "sendOftenMsg")
|
||||
{
|
||||
if (param.size())
|
||||
{
|
||||
} else if (command == "sendOftenMsg") {
|
||||
if (param.size()) {
|
||||
sendTelegramMsg(true, strTmp);
|
||||
}
|
||||
}
|
||||
@@ -76,14 +61,10 @@ public:
|
||||
~TelegramLT(){};
|
||||
};
|
||||
|
||||
void *getAPI_TelegramLT(String subtype, String param)
|
||||
{
|
||||
if (subtype == F("TelegramLT"))
|
||||
{
|
||||
void *getAPI_TelegramLT(String subtype, String param) {
|
||||
if (subtype == F("TelegramLT")) {
|
||||
return new TelegramLT(param);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
{
|
||||
{
|
||||
"menuSection": "Сенсоры",
|
||||
|
||||
"configItem": [{
|
||||
"global": 0,
|
||||
"name": "Аналоговый сенсор",
|
||||
"type": "Reading",
|
||||
"subtype": "AnalogAdc",
|
||||
"id": "t",
|
||||
"widget": "anydataTmp",
|
||||
"page": "Сенсоры",
|
||||
"descr": "Температура",
|
||||
"map": "1,1024,1,100",
|
||||
"plus": 0,
|
||||
"multiply": 1,
|
||||
"round": 1,
|
||||
"pin": 0,
|
||||
"int": 15,
|
||||
"avgSteps": 1
|
||||
}],
|
||||
|
||||
"configItem": [
|
||||
{
|
||||
"global": 0,
|
||||
"name": "Аналоговый сенсор",
|
||||
"type": "Reading",
|
||||
"subtype": "AnalogAdc",
|
||||
"id": "t",
|
||||
"widget": "anydataTmp",
|
||||
"page": "Сенсоры",
|
||||
"descr": "Температура",
|
||||
"map": "1,1024,1,100",
|
||||
"plus": 0,
|
||||
"multiply": 1,
|
||||
"round": 1,
|
||||
"pin": 0,
|
||||
"int": 15,
|
||||
"avgSteps": 1
|
||||
}
|
||||
],
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
@@ -39,13 +39,13 @@
|
||||
"int": "Количество секунд между опросами датчика."
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [],
|
||||
"esp8266_4mb": []
|
||||
"esp8266_4mb": [],
|
||||
"esp8266_1mb": [],
|
||||
"esp8266_1mb_ota": [],
|
||||
"esp8285_1mb": [],
|
||||
"esp8285_1mb_ota": []
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,18 @@
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"adafruit/Adafruit BME280 Library"
|
||||
],
|
||||
"esp8266_1mb": [
|
||||
"adafruit/Adafruit BME280 Library"
|
||||
],
|
||||
"esp8266_1mb_ota": [
|
||||
"adafruit/Adafruit BME280 Library"
|
||||
],
|
||||
"esp8285_1mb": [
|
||||
"adafruit/Adafruit BME280 Library"
|
||||
],
|
||||
"esp8285_1mb_ota": [
|
||||
"adafruit/Adafruit BME280 Library"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,18 @@
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"adafruit/Adafruit BMP280 Library"
|
||||
],
|
||||
"esp8266_1mb": [
|
||||
"adafruit/Adafruit BMP280 Library"
|
||||
],
|
||||
"esp8266_1mb_ota": [
|
||||
"adafruit/Adafruit BMP280 Library"
|
||||
],
|
||||
"esp8285_1mb": [
|
||||
"adafruit/Adafruit BMP280 Library"
|
||||
],
|
||||
"esp8285_1mb_ota": [
|
||||
"adafruit/Adafruit BMP280 Library"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ class Pzem004v : public IoTItem {
|
||||
addr = jsonReadStr(parameters, "addr");
|
||||
if (myUART) {
|
||||
pzem = new PZEMSensor(myUART, hexStringToUint8(addr));
|
||||
// раскомментируйте эту строку если нужно поменять адрес pzem
|
||||
// SerialPrint("i", "Pzem", String(pzem->setAddress(0x03)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +181,48 @@ class Pzem004pf : public IoTItem {
|
||||
~Pzem004pf(){};
|
||||
};
|
||||
|
||||
class Pzem004cmd : public IoTItem {
|
||||
private:
|
||||
String addr;
|
||||
int changeaddr;
|
||||
String setaddr;
|
||||
int reset;
|
||||
PZEMSensor* pzem;
|
||||
|
||||
public:
|
||||
Pzem004cmd(String parameters) : IoTItem(parameters) {
|
||||
jsonRead(parameters, F("addr"), addr);
|
||||
jsonRead(parameters, F("changeaddr"), changeaddr);
|
||||
jsonRead(parameters, F("setaddr"), setaddr);
|
||||
jsonRead(parameters, F("reset"), reset);
|
||||
|
||||
if (myUART) {
|
||||
pzem = new PZEMSensor(myUART, hexStringToUint8(addr));
|
||||
if (changeaddr == 1) {
|
||||
if (pzem->setAddress(hexStringToUint8(setaddr))) {
|
||||
SerialPrint("i", "Pzem", "address set: " + setaddr);
|
||||
} else {
|
||||
SerialPrint("i", "Pzem", "set adress error");
|
||||
}
|
||||
}
|
||||
if (reset == 1) {
|
||||
if (pzem->reset()) {
|
||||
SerialPrint("i", "Pzem", "reset done");
|
||||
} else {
|
||||
SerialPrint("i", "Pzem", "reset error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (pzem) {
|
||||
}
|
||||
}
|
||||
|
||||
~Pzem004cmd(){};
|
||||
};
|
||||
|
||||
void* getAPI_Pzem004(String subtype, String param) {
|
||||
if (subtype == F("Pzem004v")) {
|
||||
return new Pzem004v(param);
|
||||
@@ -191,7 +235,9 @@ void* getAPI_Pzem004(String subtype, String param) {
|
||||
} else if (subtype == F("Pzem004hz")) {
|
||||
return new Pzem004hz(param);
|
||||
} else if (subtype == F("Pzem004pf")) {
|
||||
return new Pzem004pf(param);
|
||||
return new Pzem004pf(param);
|
||||
} else if (subtype == F("Pzem004cmd")) {
|
||||
return new Pzem004cmd(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,21 @@
|
||||
"int": 15,
|
||||
"addr": "0xF8",
|
||||
"round": 1
|
||||
},
|
||||
{
|
||||
"global": 0,
|
||||
"name": "PZEM настройка",
|
||||
"type": "Reading",
|
||||
"subtype": "Pzem004cmd",
|
||||
"id": "set",
|
||||
"widget": "nil",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
"int": 15,
|
||||
"addr": "0xF8",
|
||||
"changeaddr": 0,
|
||||
"setaddr": "0x01",
|
||||
"reset": 0
|
||||
}
|
||||
],
|
||||
"about": {
|
||||
@@ -86,7 +101,7 @@
|
||||
"authorGit": "https://github.com/DmitryBorisenko33",
|
||||
"specialThanks": "Serghei Crasnicov @Serghei63",
|
||||
"moduleName": "Pzem004",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleVersion": "1.1",
|
||||
"usedRam": {
|
||||
"esp32_4mb": 15,
|
||||
"esp8266_4mb": 15
|
||||
@@ -97,13 +112,17 @@
|
||||
"Pzem004w",
|
||||
"Pzem004wh",
|
||||
"Pzem004hz",
|
||||
"Pzem004pf"
|
||||
"Pzem004pf",
|
||||
"Pzem004cmd"
|
||||
],
|
||||
"title": "Счетчик электроэнергии PZEM 004 t версии 3.0 (с модбасом). Возможно подключение трех счетчиков к одной esp для трехфазных сетей. Для этого нужно настроить разные адреса modbus в платах pzem",
|
||||
"moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры",
|
||||
"propInfo": {
|
||||
"addr": "Адрес modbus",
|
||||
"int": "Количество секунд между опросами датчика. Желателно устанавливать разные интервалы для параметров что бы опросы происходили в разное время."
|
||||
"int": "Количество секунд между опросами датчика. Желателно устанавливать разные интервалы для параметров что бы опросы происходили в разное время.",
|
||||
"changeaddr": "Поставьте этот параметр равным 1 и перезагрузите esp - будет установлен адрес указанный в setaddr. Смотрите в логе результат: [i] Pzem address set: 0x01",
|
||||
"setaddr": "Новый адрес который нужно назначить",
|
||||
"reset": "Поставьте этот параметр равным 1 и pzem будет сброшен к нулю. Смотрите в логе результат: [i] Pzem reset done"
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
|
||||
@@ -54,6 +54,18 @@
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"robtillaart/SHT2x@^0.1.1"
|
||||
],
|
||||
"esp8266_1mb": [
|
||||
"robtillaart/SHT2x@^0.1.1"
|
||||
],
|
||||
"esp8266_1mb_ota": [
|
||||
"robtillaart/SHT2x@^0.1.1"
|
||||
],
|
||||
"esp8285_1mb": [
|
||||
"robtillaart/SHT2x@^0.1.1"
|
||||
],
|
||||
"esp8285_1mb_ota": [
|
||||
"robtillaart/SHT2x@^0.1.1"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,18 @@
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"WEMOS SHT3x@1.0.0"
|
||||
],
|
||||
"esp8266_1mb": [
|
||||
"WEMOS SHT3x@1.0.0"
|
||||
],
|
||||
"esp8266_1mb_ota": [
|
||||
"WEMOS SHT3x@1.0.0"
|
||||
],
|
||||
"esp8285_1mb": [
|
||||
"WEMOS SHT3x@1.0.0"
|
||||
],
|
||||
"esp8285_1mb_ota": [
|
||||
"WEMOS SHT3x@1.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ class Loging : public IoTItem {
|
||||
IoTItem *dateIoTItem;
|
||||
|
||||
String prevDate = "";
|
||||
bool firstTimeDate = true;
|
||||
bool firstTimeInit = true;
|
||||
|
||||
long interval;
|
||||
|
||||
@@ -35,30 +35,30 @@ class Loging : public IoTItem {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' user set more points than allowed, value reset to 300");
|
||||
}
|
||||
jsonRead(parameters, F("int"), interval);
|
||||
interval = interval * 1000 * 60; //приводим к милисекундам
|
||||
interval = interval * 1000 * 60; // приводим к милисекундам
|
||||
jsonRead(parameters, F("keepdays"), keepdays);
|
||||
|
||||
//создадим экземпляр класса даты
|
||||
// создадим экземпляр класса даты
|
||||
dateIoTItem = (IoTItem *)getAPI_Date("{\"id\": \"" + id + "-date\",\"int\":\"20\",\"subtype\":\"date\"}");
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
String value = getItemValue(logid);
|
||||
//если значение логгирования пустое
|
||||
// если значение логгирования пустое
|
||||
if (value == "") {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' loging value is empty, return");
|
||||
return;
|
||||
}
|
||||
|
||||
//если время не было получено из интернета
|
||||
// если время не было получено из интернета
|
||||
if (!isTimeSynch) {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' Сant loging - time not synchronized, return");
|
||||
return;
|
||||
@@ -71,16 +71,16 @@ class Loging : public IoTItem {
|
||||
jsonWriteInt(logData, "x", unixTime);
|
||||
jsonWriteFloat(logData, "y1", value.toFloat());
|
||||
|
||||
//прочитаем путь к файлу последнего сохранения
|
||||
// прочитаем путь к файлу последнего сохранения
|
||||
String filePath = readDataDB(id);
|
||||
|
||||
//если данные о файле отсутствуют, создадим новый
|
||||
// если данные о файле отсутствуют, создадим новый
|
||||
if (filePath == "failed" || filePath == "") {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' file path not found, start create new file");
|
||||
createNewFileWithData(logData);
|
||||
return;
|
||||
} else {
|
||||
//если файл все же есть но был создан не сегодня, то создаем сегодняшний
|
||||
// если файл все же есть но был создан не сегодня, то создаем сегодняшний
|
||||
if (getTodayDateDotFormated() != getDateDotFormatedFromUnix(getFileUnixLocalTime(filePath))) {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' file too old, start create new file");
|
||||
createNewFileWithData(logData);
|
||||
@@ -88,30 +88,31 @@ class Loging : public IoTItem {
|
||||
}
|
||||
}
|
||||
|
||||
//считаем количество строк и определяем размер файла
|
||||
// считаем количество строк и определяем размер файла
|
||||
size_t size = 0;
|
||||
int lines = countJsonObj(filePath, size);
|
||||
SerialPrint("i", F("Loging"), "'" + id + "' " + "lines = " + String(lines) + ", size = " + String(size));
|
||||
|
||||
//если количество строк до заданной величины и дата не менялась
|
||||
// если количество строк до заданной величины и дата не менялась
|
||||
if (lines <= points && !hasDayChanged()) {
|
||||
//просто добавим в существующий файл новые данные
|
||||
// просто добавим в существующий файл новые данные
|
||||
addNewDataToExistingFile(filePath, logData);
|
||||
//если больше или поменялась дата то создадим следующий файл
|
||||
// если больше или поменялась дата то создадим следующий файл
|
||||
} else {
|
||||
createNewFileWithData(logData);
|
||||
}
|
||||
//запускаем процедуру удаления старых файлов если память переполняется
|
||||
// запускаем процедуру удаления старых файлов если память переполняется
|
||||
deleteLastFile();
|
||||
}
|
||||
void SetDoByInterval(String valse) {
|
||||
|
||||
void SetDoByInterval(String valse) {
|
||||
String value = valse;
|
||||
//если значение логгирования пустое
|
||||
// если значение логгирования пустое
|
||||
if (value == "") {
|
||||
SerialPrint("E", F("LogingEvent"), "'" + id + "' loging value is empty, return");
|
||||
return;
|
||||
}
|
||||
//если время не было получено из интернета
|
||||
// если время не было получено из интернета
|
||||
if (!isTimeSynch) {
|
||||
SerialPrint("E", F("LogingEvent"), "'" + id + "' Сant loging - time not synchronized, return");
|
||||
return;
|
||||
@@ -120,16 +121,16 @@ void SetDoByInterval(String valse) {
|
||||
String logData;
|
||||
jsonWriteInt(logData, "x", unixTime);
|
||||
jsonWriteFloat(logData, "y1", value.toFloat());
|
||||
//прочитаем путь к файлу последнего сохранения
|
||||
// прочитаем путь к файлу последнего сохранения
|
||||
String filePath = readDataDB(id);
|
||||
|
||||
//если данные о файле отсутствуют, создадим новый
|
||||
// если данные о файле отсутствуют, создадим новый
|
||||
if (filePath == "failed" || filePath == "") {
|
||||
SerialPrint("E", F("LogingEvent"), "'" + id + "' file path not found, start create new file");
|
||||
createNewFileWithData(logData);
|
||||
return;
|
||||
} else {
|
||||
//если файл все же есть но был создан не сегодня, то создаем сегодняшний
|
||||
// если файл все же есть но был создан не сегодня, то создаем сегодняшний
|
||||
if (getTodayDateDotFormated() != getDateDotFormatedFromUnix(getFileUnixLocalTime(filePath))) {
|
||||
SerialPrint("E", F("LogingEvent"), "'" + id + "' file too old, start create new file");
|
||||
createNewFileWithData(logData);
|
||||
@@ -137,39 +138,38 @@ void SetDoByInterval(String valse) {
|
||||
}
|
||||
}
|
||||
|
||||
//считаем количество строк и определяем размер файла
|
||||
// считаем количество строк и определяем размер файла
|
||||
size_t size = 0;
|
||||
int lines = countJsonObj(filePath, size);
|
||||
SerialPrint("i", F("LogingEvent"), "'" + id + "' " + "lines = " + String(lines) + ", size = " + String(size));
|
||||
|
||||
//если количество строк до заданной величины и дата не менялась
|
||||
// если количество строк до заданной величины и дата не менялась
|
||||
if (lines <= points && !hasDayChanged()) {
|
||||
//просто добавим в существующий файл новые данные
|
||||
// просто добавим в существующий файл новые данные
|
||||
addNewDataToExistingFile(filePath, logData);
|
||||
//если больше или поменялась дата то создадим следующий файл
|
||||
// если больше или поменялась дата то создадим следующий файл
|
||||
} else {
|
||||
createNewFileWithData(logData);
|
||||
}
|
||||
//запускаем процедуру удаления старых файлов если память переполняется
|
||||
// запускаем процедуру удаления старых файлов если память переполняется
|
||||
deleteLastFile();
|
||||
|
||||
}
|
||||
void createNewFileWithData(String &logData) {
|
||||
logData = logData + ",";
|
||||
String path = "/lg/" + id + "/" + String(unixTimeShort) + ".txt"; //создадим путь вида /lg/id/133256622333.txt
|
||||
//создадим пустой файл
|
||||
if (writeEmptyFile(path) != "sucсess") {
|
||||
String path = "/lg/" + id + "/" + String(unixTimeShort) + ".txt"; // создадим путь вида /lg/id/133256622333.txt
|
||||
// создадим пустой файл
|
||||
if (writeEmptyFile(path) != "success") {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' file writing error, return");
|
||||
return;
|
||||
}
|
||||
|
||||
//запишем в него данные
|
||||
if (addFile(path, logData) != "sucсess") {
|
||||
// запишем в него данные
|
||||
if (addFile(path, logData) != "success") {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' data writing error, return");
|
||||
return;
|
||||
}
|
||||
//запишем путь к нему в базу данных
|
||||
if (saveDataDB(id, path) != "sucсess") {
|
||||
// запишем путь к нему в базу данных
|
||||
if (saveDataDB(id, path) != "success") {
|
||||
SerialPrint("E", F("Loging"), "'" + id + "' db file writing error, return");
|
||||
return;
|
||||
}
|
||||
@@ -178,20 +178,21 @@ void SetDoByInterval(String valse) {
|
||||
|
||||
void addNewDataToExistingFile(String &path, String &logData) {
|
||||
logData = logData + ",";
|
||||
if (addFile(path, logData) != "sucсess") {
|
||||
if (addFile(path, logData) != "success") {
|
||||
SerialPrint("i", F("Loging"), "'" + id + "' file writing error, return");
|
||||
return;
|
||||
};
|
||||
SerialPrint("i", F("Loging"), "'" + id + "' loging in file http://" + WiFi.localIP().toString() + path);
|
||||
}
|
||||
|
||||
// данная функция уже перенесена в ядро и будет удалена в последствии
|
||||
bool hasDayChanged() {
|
||||
bool changed = false;
|
||||
String currentDate = getTodayDateDotFormated();
|
||||
if (!firstTimeDate) {
|
||||
if (!firstTimeInit) {
|
||||
if (prevDate != currentDate) {
|
||||
changed = true;
|
||||
SerialPrint("i", F("NTP"), "Change day event");
|
||||
SerialPrint("i", F("NTP"), F("Change day event"));
|
||||
#if defined(ESP8266)
|
||||
FileFS.gc();
|
||||
#endif
|
||||
@@ -199,7 +200,7 @@ void SetDoByInterval(String valse) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
firstTimeDate = false;
|
||||
firstTimeInit = false;
|
||||
prevDate = currentDate;
|
||||
return changed;
|
||||
}
|
||||
@@ -242,7 +243,7 @@ void SetDoByInterval(String valse) {
|
||||
|
||||
filesList = deleteBeforeDelimiter(filesList, ";");
|
||||
}
|
||||
//если данных нет отправляем пустой грфик
|
||||
// если данных нет отправляем пустой грфик
|
||||
if (noData) {
|
||||
clearValue();
|
||||
}
|
||||
@@ -308,17 +309,17 @@ void SetDoByInterval(String valse) {
|
||||
difference = currentMillis - prevMillis;
|
||||
if (difference >= interval) {
|
||||
prevMillis = millis();
|
||||
if(interval != 0){
|
||||
if (interval != 0) {
|
||||
this->doByInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void regEvent(const String& value, const String& consoleInfo, bool error = false, bool genEvent = true) {
|
||||
void regEvent(const String &value, const String &consoleInfo, bool error = false, bool genEvent = true) {
|
||||
String userDate = getItemValue(id + "-date");
|
||||
String currentDate = getTodayDateDotFormated();
|
||||
//отправляем в график данные только когда выбран сегодняшний день
|
||||
// отправляем в график данные только когда выбран сегодняшний день
|
||||
if (userDate == currentDate) {
|
||||
// generateEvent(_id, value);
|
||||
// publishStatusMqtt(_id, value);
|
||||
@@ -328,16 +329,16 @@ void SetDoByInterval(String valse) {
|
||||
}
|
||||
}
|
||||
|
||||
//просто максимальное количество точек
|
||||
// просто максимальное количество точек
|
||||
int calculateMaxCount() {
|
||||
return 86400;
|
||||
}
|
||||
|
||||
//путь вида: /lg/log/1231231.txt
|
||||
// путь вида: /lg/log/1231231.txt
|
||||
unsigned long getFileUnixLocalTime(String path) {
|
||||
return gmtTimeToLocal(selectToMarkerLast(deleteToMarkerLast(path, "."), "/").toInt() + START_DATETIME);
|
||||
}
|
||||
void setValue(const IoTValue& Value, bool genEvent = true){
|
||||
void setValue(const IoTValue &Value, bool genEvent = true) {
|
||||
value = Value;
|
||||
this->SetDoByInterval(String(value.valD));
|
||||
SerialPrint("i", "Loging", "setValue:" + String(value.valD));
|
||||
@@ -364,15 +365,15 @@ class Date : public IoTItem {
|
||||
value.isDecimal = false;
|
||||
}
|
||||
|
||||
void setValue(const String& valStr, bool genEvent = true) {
|
||||
void setValue(const String &valStr, bool genEvent = true) {
|
||||
value.valS = valStr;
|
||||
setValue(value, genEvent);
|
||||
}
|
||||
|
||||
void setValue(const IoTValue& Value, bool genEvent = true) {
|
||||
void setValue(const IoTValue &Value, bool genEvent = true) {
|
||||
value = Value;
|
||||
regEvent(value.valS, "", false, genEvent);
|
||||
//отправка данных при изменении даты
|
||||
// отправка данных при изменении даты
|
||||
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getSubtype() == "Loging") {
|
||||
if ((*it)->getID() == selectToMarker(id, "-")) {
|
||||
|
||||
@@ -9,6 +9,8 @@ class LogingDaily : public IoTItem {
|
||||
String id;
|
||||
String filesList = "";
|
||||
|
||||
String descr;
|
||||
|
||||
int _publishType = -2;
|
||||
int _wsNum = -1;
|
||||
|
||||
@@ -16,10 +18,12 @@ class LogingDaily : public IoTItem {
|
||||
|
||||
int testMode;
|
||||
|
||||
int telegram;
|
||||
|
||||
IoTItem *dateIoTItem;
|
||||
|
||||
String prevDate = "";
|
||||
bool firstTimeDate = true;
|
||||
bool firstTimeInit = true;
|
||||
|
||||
long interval;
|
||||
|
||||
@@ -29,13 +33,15 @@ class LogingDaily : public IoTItem {
|
||||
jsonRead(parameters, F("id"), id);
|
||||
jsonRead(parameters, F("points"), points);
|
||||
jsonRead(parameters, F("test"), testMode);
|
||||
jsonRead(parameters, F("telegram"), telegram);
|
||||
jsonRead(parameters, F("descr"), descr);
|
||||
|
||||
if (points > 365) {
|
||||
points = 365;
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' user set more points than allowed, value reset to 365");
|
||||
}
|
||||
jsonRead(parameters, F("int"), interval);
|
||||
interval = interval * 1000 * 60; //приводим к милисекундам
|
||||
interval = interval * 1000 * 60; // приводим к милисекундам
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
@@ -45,7 +51,7 @@ class LogingDaily : public IoTItem {
|
||||
}
|
||||
|
||||
void execute() {
|
||||
//если объект логгирования не был создан
|
||||
// если объект логгирования не был создан
|
||||
if (!isItemExist(logid)) {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' LogingDaily object not exist, return");
|
||||
return;
|
||||
@@ -53,51 +59,60 @@ class LogingDaily : public IoTItem {
|
||||
|
||||
String value = getItemValue(logid);
|
||||
|
||||
//если значение логгирования пустое
|
||||
// если значение логгирования пустое
|
||||
if (value == "") {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' LogingDaily value is empty, return");
|
||||
return;
|
||||
}
|
||||
|
||||
//если время не было получено из интернета
|
||||
// если время не было получено из интернета
|
||||
if (!isTimeSynch) {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' Сant LogingDaily - time not synchronized, return");
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' Cant LogingDaily - time not synchronized, return");
|
||||
return;
|
||||
}
|
||||
|
||||
String logData;
|
||||
|
||||
float currentValue = value.toFloat();
|
||||
//прочитаем предудущее значение
|
||||
// прочитаем предудущее значение
|
||||
float prevValue = readDataDB(id + "-v").toFloat();
|
||||
//сохраним в базу данных текущее значение, понадобится в следующие сутки
|
||||
// сохраним в базу данных текущее значение, понадобится в следующие сутки
|
||||
saveDataDB(id + "-v", value);
|
||||
|
||||
float difference = currentValue - prevValue;
|
||||
|
||||
if (telegram == 1) {
|
||||
String msg = descr + ": total " + String(currentValue) + ", consumed " + String(difference);
|
||||
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getSubtype() == "TelegramLT" || "Telegram") {
|
||||
(*it)->sendTelegramMsg(false, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsonWriteInt(logData, "x", unixTime - 120);
|
||||
jsonWriteFloat(logData, "y1", difference);
|
||||
|
||||
//прочитаем путь к файлу последнего сохранения
|
||||
// прочитаем путь к файлу последнего сохранения
|
||||
String filePath = readDataDB(id);
|
||||
|
||||
//если данные о файле отсутствуют, создадим новый
|
||||
// если данные о файле отсутствуют, создадим новый
|
||||
if (filePath == "failed" || filePath == "") {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' file path not found, start create new file");
|
||||
createNewFileWithData(logData);
|
||||
return;
|
||||
}
|
||||
|
||||
//считаем количество строк и определяем размер файла
|
||||
// считаем количество строк и определяем размер файла
|
||||
size_t size = 0;
|
||||
int lines = countJsonObj(filePath, size);
|
||||
SerialPrint("i", F("LogingDaily"), "'" + id + "' " + "lines = " + String(lines) + ", size = " + String(size));
|
||||
|
||||
//если количество строк до заданной величины и дата не менялась
|
||||
// если количество строк до заданной величины и дата не менялась
|
||||
if (lines <= points && !hasDayChanged()) {
|
||||
//просто добавим в существующий файл новые данные
|
||||
// просто добавим в существующий файл новые данные
|
||||
addNewDataToExistingFile(filePath, logData);
|
||||
//если больше или поменялась дата то создадим следующий файл
|
||||
// если больше или поменялась дата то создадим следующий файл
|
||||
} else {
|
||||
createNewFileWithData(logData);
|
||||
}
|
||||
@@ -106,20 +121,20 @@ class LogingDaily : public IoTItem {
|
||||
void createNewFileWithData(String &logData) {
|
||||
logData = logData + ",";
|
||||
|
||||
String path = "/lgd/" + id + "/" + id + ".txt"; //создадим путь вида /lgd/id/id.txt
|
||||
//создадим пустой файл
|
||||
if (writeEmptyFile(path) != "sucсess") {
|
||||
String path = "/lgd/" + id + "/" + id + ".txt"; // создадим путь вида /lgd/id/id.txt
|
||||
// создадим пустой файл
|
||||
if (writeEmptyFile(path) != "success") {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' file writing error, return");
|
||||
return;
|
||||
}
|
||||
|
||||
//запишем в него данные
|
||||
if (addFile(path, logData) != "sucсess") {
|
||||
// запишем в него данные
|
||||
if (addFile(path, logData) != "success") {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' data writing error, return");
|
||||
return;
|
||||
}
|
||||
//запишем путь к нему в базу данных
|
||||
if (saveDataDB(id, path) != "sucсess") {
|
||||
// запишем путь к нему в базу данных
|
||||
if (saveDataDB(id, path) != "success") {
|
||||
SerialPrint("E", F("LogingDaily"), "'" + id + "' db file writing error, return");
|
||||
return;
|
||||
}
|
||||
@@ -128,7 +143,7 @@ class LogingDaily : public IoTItem {
|
||||
|
||||
void addNewDataToExistingFile(String &path, String &logData) {
|
||||
logData = logData + ",";
|
||||
if (addFile(path, logData) != "sucсess") {
|
||||
if (addFile(path, logData) != "success") {
|
||||
SerialPrint("i", F("LogingDaily"), "'" + id + "' file writing error, return");
|
||||
return;
|
||||
};
|
||||
@@ -138,7 +153,7 @@ class LogingDaily : public IoTItem {
|
||||
bool hasDayChanged() {
|
||||
bool changed = false;
|
||||
String currentDate = getTodayDateDotFormated();
|
||||
if (!firstTimeDate) {
|
||||
if (!firstTimeInit) {
|
||||
if (prevDate != currentDate) {
|
||||
changed = true;
|
||||
SerialPrint("i", F("NTP"), "Change day event");
|
||||
@@ -149,7 +164,7 @@ class LogingDaily : public IoTItem {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
firstTimeDate = false;
|
||||
firstTimeInit = false;
|
||||
prevDate = currentDate;
|
||||
return changed;
|
||||
}
|
||||
@@ -221,10 +236,20 @@ class LogingDaily : public IoTItem {
|
||||
}
|
||||
}
|
||||
|
||||
//просто максимальное количество точек
|
||||
// просто максимальное количество точек
|
||||
int calculateMaxCount() {
|
||||
return 86400;
|
||||
}
|
||||
|
||||
void onModuleOrder(String &key, String &value) {
|
||||
if (key == "defvalue") {
|
||||
saveDataDB(id + "-v", value);
|
||||
SerialPrint("i", F("LogingDaily"), "User set default value: " + value);
|
||||
} else if (key == "reset") {
|
||||
clearHistory();
|
||||
SerialPrint("i", F("LogingDaily"), F("User clean chart history"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void *getAPI_LogingDaily(String subtype, String param) {
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
"int": 1,
|
||||
"logid": "t",
|
||||
"points": 365,
|
||||
"column": 0
|
||||
"telegram": 0,
|
||||
"test": 0,
|
||||
"btn-defvalue": 0,
|
||||
"btn-reset": "nil"
|
||||
}
|
||||
],
|
||||
"about": {
|
||||
@@ -23,7 +26,7 @@
|
||||
"authorGit": "https://github.com/DmitryBorisenko33",
|
||||
"specialThanks": "@itsid1 @Valiuhaaa Serg",
|
||||
"moduleName": "LogingDaily",
|
||||
"moduleVersion": "3.0",
|
||||
"moduleVersion": "3.1",
|
||||
"usedRam": {
|
||||
"esp32_4mb": 15,
|
||||
"esp8266_4mb": 15
|
||||
@@ -34,7 +37,8 @@
|
||||
"int": "Интервал логирования в мнутах, частота проверки смены суток в минутах. Не рекомендуется менять",
|
||||
"logid": "ID накопительной величины которую будем логировать",
|
||||
"points": "Максимальное количество точек",
|
||||
"column": "Режим тестирования - график будет обновляться не раз в сутки, а кадый заданный в int интервал. Суточные столбики - 0, Минутные столбики - 1"
|
||||
"telegram": "График будет отправлять в телеграм репорт с расходами каждый день",
|
||||
"test": "Параметр необходим для разработчиков. Режим тестирования. График будет обновляться не раз в сутки, а кадый заданный в int интервал."
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "utils/FileUtils.h"
|
||||
|
||||
//данная функция записывает файл из буфера страницами указанного размера
|
||||
// данная функция записывает файл из буфера страницами указанного размера
|
||||
void writeFileUint8tByFrames(const String& filename, uint8_t*& big_buf, size_t length, size_t headerLenth, size_t frameSize) {
|
||||
String path = filepath(filename);
|
||||
auto file = FileFS.open(path, FILE_WRITE);
|
||||
@@ -71,7 +71,7 @@ const String writeFile(const String& filename, const String& str) {
|
||||
}
|
||||
file.print(str);
|
||||
file.close();
|
||||
return "sucсess";
|
||||
return "success";
|
||||
onFlashWrite();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ const String writeEmptyFile(const String& filename) {
|
||||
return "failed";
|
||||
}
|
||||
file.close();
|
||||
return "sucсess";
|
||||
return "success";
|
||||
onFlashWrite();
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ const String addFileLn(const String& filename, const String& str) {
|
||||
}
|
||||
file.println(str);
|
||||
file.close();
|
||||
return "sucсess";
|
||||
return "success";
|
||||
onFlashWrite();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ const String addFile(const String& filename, const String& str) {
|
||||
}
|
||||
file.print(str);
|
||||
file.close();
|
||||
return "sucсess";
|
||||
return "success";
|
||||
onFlashWrite();
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ bool cutFile(const String& src, const String& dst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//функция считает количество строк в файле
|
||||
// функция считает количество строк в файле
|
||||
size_t countJsonObj(const String filename, size_t& size) {
|
||||
size_t cnt = -1;
|
||||
String path = filepath(filename);
|
||||
@@ -180,7 +180,7 @@ size_t countJsonObj(const String filename, size_t& size) {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
//удаляем файл
|
||||
// удаляем файл
|
||||
void removeFile(const String& filename) {
|
||||
String path = filepath(filename);
|
||||
if (FileFS.exists(path)) {
|
||||
@@ -216,8 +216,8 @@ String readDataDB(String id) {
|
||||
void cleanLogs() {
|
||||
SerialPrint("i", "Files", "cleanLogs");
|
||||
cleanDirectory("/db");
|
||||
//обращение к логированию из ядра
|
||||
//очистка данных всех экземпляров графиков
|
||||
// обращение к логированию из ядра
|
||||
// очистка данных всех экземпляров графиков
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
|
||||
(*it)->clearHistory();
|
||||
@@ -225,7 +225,7 @@ void cleanLogs() {
|
||||
}
|
||||
}
|
||||
|
||||
//очищаем директорию с файлами
|
||||
// очищаем директорию с файлами
|
||||
void cleanDirectory(String path) {
|
||||
String filesList = getFilesList(path);
|
||||
int i = 0;
|
||||
@@ -241,7 +241,7 @@ void cleanDirectory(String path) {
|
||||
}
|
||||
}
|
||||
|
||||
//счетчик количества записей на флешь за сеанс
|
||||
// счетчик количества записей на флешь за сеанс
|
||||
void onFlashWrite() {
|
||||
flashWriteNumber++;
|
||||
// SerialPrint(F("->"), F("FS"), F("write data on flash"));
|
||||
|
||||
@@ -32,4 +32,31 @@ const String prettySeconds(unsigned long time_s) {
|
||||
|
||||
const String prettyMillis(unsigned long time_ms) {
|
||||
return prettySeconds(time_ms / 1000);
|
||||
}
|
||||
|
||||
const String prettyMinutsTimeout(unsigned long time_m) {
|
||||
unsigned long tmp = time_m * 60;
|
||||
unsigned long seconds;
|
||||
unsigned long minutes;
|
||||
unsigned long hours;
|
||||
unsigned long days;
|
||||
seconds = tmp % 60;
|
||||
tmp = tmp / 60;
|
||||
|
||||
minutes = tmp % 60;
|
||||
tmp = tmp / 60;
|
||||
|
||||
hours = tmp % 24;
|
||||
days = tmp / 24;
|
||||
|
||||
char buf[32];
|
||||
|
||||
if (days) {
|
||||
sprintf_P(buf, "%d day %d hr %d min", days, hours, minutes, seconds);
|
||||
} else if (hours && !days) {
|
||||
sprintf_P(buf, "%d hr %d min", hours, minutes);
|
||||
} else {
|
||||
sprintf_P(buf, "%d min", minutes);
|
||||
}
|
||||
return String(buf);
|
||||
}
|
||||
Reference in New Issue
Block a user