diff --git a/include/classes/IoTItem.h b/include/classes/IoTItem.h index 62884956..00d4a68c 100644 --- a/include/classes/IoTItem.h +++ b/include/classes/IoTItem.h @@ -16,8 +16,8 @@ class IoTItem { virtual void doByInterval(); virtual IoTValue execute(String command, std::vector& param); - virtual void regEvent(String value, String consoleInfo); - virtual void regEvent(float value, String consoleInfo); + virtual void regEvent(String value, String consoleInfo, bool error = false); + virtual void regEvent(float value, String consoleInfo, bool error = false); String getSubtype(); @@ -69,7 +69,7 @@ class IoTItem { IoTItem* findIoTItem(String name); // поиск экземпляра элемента модуля по имени String getItemValue(String name); // поиск плюс получение значения bool isItemExist(String name); // существует ли айтем -StaticJsonDocument* getLocalItemsAsJSON(); // сбор всех локальных занчений Items +StaticJsonDocument* getLocalItemsAsJSON(); // сбор всех локальных значений Items class externalVariable : IoTItem { // объект, создаваемый при получении информации о событии на другом контроллере для хранения информации о событии указанное время diff --git a/include/utils/SerialPrint.h b/include/utils/SerialPrint.h index 62efd173..ee3a2d82 100644 --- a/include/utils/SerialPrint.h +++ b/include/utils/SerialPrint.h @@ -1,5 +1,6 @@ #pragma once #include "Global.h" #include "utils/TimeUtils.h" +#include "classes/IoTItem.h" -void SerialPrint(String errorLevel, String module, String msg); \ No newline at end of file +void SerialPrint(String errorLevel, String module, String msg, String itemId = ""); \ No newline at end of file diff --git a/include/utils/StringUtils.h b/include/utils/StringUtils.h index da9468cb..9f2f9d75 100644 --- a/include/utils/StringUtils.h +++ b/include/utils/StringUtils.h @@ -32,7 +32,7 @@ size_t itemsCount2(String str, const String& separator); char* stringToChar(String& str); -size_t itemsCount(String& str, const char* delim); +//size_t itemsCount(String& str, const char* delim); boolean isDigitStr(const String& str); @@ -41,3 +41,5 @@ boolean isDigitDotCommaStr(const String& str); String prettyBytes(size_t size); String uint64ToString(uint64_t input, uint8_t base = 10); + +String cleanString(String str); diff --git a/src/classes/IoTItem.cpp b/src/classes/IoTItem.cpp index 0c50e7f0..37a59850 100644 --- a/src/classes/IoTItem.cpp +++ b/src/classes/IoTItem.cpp @@ -10,7 +10,7 @@ IoTItem::IoTItem(String parameters) { jsonRead(parameters, F("int"), _interval); if (_interval == 0) enableDoByInt = false; _interval = _interval * 1000; - jsonRead(parameters, F("subtype"), _subtype); + jsonRead(parameters, F("subtype"), _subtype, false); jsonRead(parameters, F("id"), _id); if (!jsonRead(parameters, F("multiply"), _multiply, false)) _multiply = 1; if (!jsonRead(parameters, F("plus"), _plus, false)) _plus = 0; @@ -79,7 +79,7 @@ void IoTItem::setValue(IoTValue Value, bool generateEvent) { } //когда событие случилось -void IoTItem::regEvent(String value, String consoleInfo = "") { +void IoTItem::regEvent(String value, String consoleInfo, bool error) { if (_needSave) { jsonWriteStr_(valuesFlashJson, _id, value); needSaveValues = true; @@ -95,8 +95,8 @@ void IoTItem::regEvent(String value, String consoleInfo = "") { // if (_global) { // SerialPrint("i", F("=>ALLMQTT"), "Broadcast event: "); // } - //отправка события другим устройствам в сети============================== - if (jsonReadBool(settingsFlashJson, "mqttin")) { + //отправка события другим устройствам в сети если не было ошибки============================== + if (jsonReadBool(settingsFlashJson, "mqttin") && _global && !error) { String json = "{}"; jsonWriteStr_(json, "id", _id); jsonWriteStr_(json, "val", value); @@ -120,21 +120,20 @@ String IoTItem::getRoundValue() { } } -void IoTItem::regEvent(float regvalue, String consoleInfo = "") { +void IoTItem::regEvent(float regvalue, String consoleInfo, bool error) { value.valD = regvalue; if (_multiply) value.valD = value.valD * _multiply; if (_plus) value.valD = value.valD + _plus; if (_map1 != _map2) value.valD = map(value.valD, _map1, _map2, _map3, _map4); - regEvent(getRoundValue(), consoleInfo); + regEvent(getRoundValue(), consoleInfo, error); } void IoTItem::doByInterval() {} IoTValue IoTItem::execute(String command, std::vector& param) { return {}; } -//захрена эта хрень? - самому пригодилась сорян Илья String IoTItem::getSubtype() { return _subtype; } @@ -166,7 +165,7 @@ IoTGpio* IoTItem::getGpioDriver() { externalVariable::externalVariable(String parameters) : IoTItem(parameters) { prevMillis = millis(); // запоминаем текущее значение таймера для выполения doByInterval после int сек iAmLocal = false; // указываем, что это сущность прилетела из сети - Serial.printf("Call from externalVariable: parameters %s %d\n", parameters.c_str(), _interval); + //Serial.printf("Call from externalVariable: parameters %s %d\n", parameters.c_str(), _interval); } externalVariable::~externalVariable() { diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 0779d816..7964852a 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -104,6 +104,7 @@ class VariableExprAST : public ExprAST { return &(Item->value); } + SerialPrint("E", Name, "Элемент не найден или соединение потеряно", Name); return nullptr; // Item не найден. } }; @@ -145,90 +146,92 @@ class BinaryExprAST : public ExprAST { if (RHS == nullptr || LHS == nullptr) return nullptr; IoTValue *rhs = RHS->exec(); // получаем значение правого операнда для возможного использования в операции присваивания + if (rhs == nullptr) return nullptr; if (Op == '=' && LHS->setValue(rhs)) { // если установка значения не поддерживается, т.е. слева не переменная, то работаем по другим комбинациям далее return rhs; // иначе возвращаем присвоенное значение справа } IoTValue *lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда + if (lhs == nullptr) return nullptr; - if (lhs != nullptr && rhs != nullptr) { - if (lhs->isDecimal && rhs->isDecimal) { - switch (Op) { - case '>': - val.valD = lhs->valD > rhs->valD; - break; - case '<': - val.valD = lhs->valD < rhs->valD; - break; - case tok_lesseq: - val.valD = lhs->valD <= rhs->valD; - break; - case tok_greateq: - val.valD = lhs->valD >= rhs->valD; - break; - case tok_equal: - val.valD = lhs->valD == rhs->valD; - break; - case tok_notequal: - val.valD = lhs->valD != rhs->valD; - break; + + if (lhs->isDecimal && rhs->isDecimal) { + switch (Op) { + case '>': + val.valD = lhs->valD > rhs->valD; + break; + case '<': + val.valD = lhs->valD < rhs->valD; + break; + case tok_lesseq: + val.valD = lhs->valD <= rhs->valD; + break; + case tok_greateq: + val.valD = lhs->valD >= rhs->valD; + break; + case tok_equal: + val.valD = lhs->valD == rhs->valD; + break; + case tok_notequal: + val.valD = lhs->valD != rhs->valD; + break; - case '+': - val.valD = lhs->valD + rhs->valD; - break; - case '-': - val.valD = lhs->valD - rhs->valD; - break; - case '*': - val.valD = lhs->valD * rhs->valD; - break; - case '/': - if (rhs->valD != 0) - val.valD = lhs->valD / rhs->valD; - else - val.valD = 3.4E+38; - break; + case '+': + val.valD = lhs->valD + rhs->valD; + break; + case '-': + val.valD = lhs->valD - rhs->valD; + break; + case '*': + val.valD = lhs->valD * rhs->valD; + break; + case '/': + if (rhs->valD != 0) + val.valD = lhs->valD / rhs->valD; + else + val.valD = 3.4E+38; + break; - case '|': - val.valD = lhs->valD || rhs->valD; - break; - case '&': - val.valD = lhs->valD && rhs->valD; - break; + case '|': + val.valD = lhs->valD || rhs->valD; + break; + case '&': + val.valD = lhs->valD && rhs->valD; + break; - default: - break; - } - return &val; - } - - if (!lhs->isDecimal || !rhs->isDecimal) { - if (lhs->isDecimal) - lhsStr = (String)lhs->valD; - else - lhsStr = lhs->valS; - if (rhs->isDecimal) - rhsStr = (String)rhs->valD; - else - rhsStr = rhs->valS; - switch (Op) { - case tok_equal: - val.valD = compStr(lhsStr, rhsStr); - break; - - case '+': - val.valS = lhsStr + rhsStr; - val.valD = 1; - val.isDecimal = false; - break; - - default: - break; - } - return &val; + default: + break; } + return &val; } + + if (!lhs->isDecimal || !rhs->isDecimal) { + if (lhs->isDecimal) + lhsStr = (String)lhs->valD; + else + lhsStr = lhs->valS; + if (rhs->isDecimal) + rhsStr = (String)rhs->valD; + else + rhsStr = rhs->valS; + switch (Op) { + case tok_equal: + val.valD = compStr(lhsStr, rhsStr); + break; + + case '+': + val.valS = lhsStr + rhsStr; + val.valD = 1; + val.isDecimal = false; + break; + + default: + break; + } + return &val; + } + return &val; } @@ -321,6 +324,7 @@ enum SysOp { sysop_gethhmm, sysop_gethhmmss, sysop_getTime, + sysop_getRSSI, sysop_getIP, sysop_mqttPub, sysop_getUptime @@ -404,6 +408,10 @@ IoTValue sysExecute(SysOp command, std::vector ¶m) { #endif } break; + case sysop_getRSSI: + value.valD = WiFi.RSSI(); + value.isDecimal = true; + break; case sysop_getIP: value.valS = jsonReadStr(settingsFlashJson, F("ip")); value.isDecimal = false; @@ -460,6 +468,8 @@ class SysCallExprAST : public ExprAST { operation = sysop_getMonth; else if (Callee == "getDay") operation = sysop_getDay; + else if (Callee == "getRSSI") + operation = sysop_getRSSI; else if (Callee == "getIP") operation = sysop_getIP; else if (Callee == "mqttPub") @@ -537,7 +547,8 @@ class IfExprAST : public ExprAST { return nullptr; //&zeroIotVal; } - if (cond_ret->isDecimal && cond_ret->valD) { + // если число больше нуля или строка не равна пустой, то считаем условие выполненным + if (cond_ret->isDecimal && cond_ret->valD || !(cond_ret->isDecimal) && cond_ret->valS != "") { if (Then == nullptr) return nullptr; res_ret = Then->exec(); } else { diff --git a/src/modules/sceninfo.json b/src/modules/sceninfo.json index b358033e..6f26cc47 100644 --- a/src/modules/sceninfo.json +++ b/src/modules/sceninfo.json @@ -44,6 +44,11 @@ "descr": "Погрузить ESP в глубокий сон. Вывод из сна с перезагрузкой. Для ESP8266 необходимо соединить gpio 16 и RST", "params": ["ЧислоСекунд"] }, + { + "name": "getRSSI", + "descr": "Получить величину уровня принимаемого сигнала WI-FI.", + "params": [] + }, { "name": "getIP", "descr": "Получить строку IP ESP", diff --git a/src/modules/virtual/Loging/Loging.cpp b/src/modules/virtual/Loging/Loging.cpp index d9ccb976..d9f5fdde 100644 --- a/src/modules/virtual/Loging/Loging.cpp +++ b/src/modules/virtual/Loging/Loging.cpp @@ -263,7 +263,7 @@ class Loging : public IoTItem { } } - void regEvent(String value, String consoleInfo = "") { + void regEvent(String value, String consoleInfo, bool error = false) { String userDate = getItemValue(id + "-date"); String currentDate = getTodayDateDotFormated(); //отправляем в график данные только когда выбран сегодняшний день diff --git a/src/utils/SerialPrint.cpp b/src/utils/SerialPrint.cpp index 6287029c..22e8b96c 100644 --- a/src/utils/SerialPrint.cpp +++ b/src/utils/SerialPrint.cpp @@ -1,14 +1,23 @@ #include "utils/SerialPrint.h" -void SerialPrint(String errorLevel, String module, String msg) { - String tosend; - - tosend = prettyMillis(millis()); - +void SerialPrint(String errorLevel, String module, String msg, String itemId) { + String tosend = prettyMillis(millis()); tosend = tosend + " [" + errorLevel + "] [" + module + "] " + msg; Serial.println(tosend); + if (errorLevel == "E") { + msg = cleanString(msg); + // создаем событие об ошибке для возможной реакции в сценарии + if (itemId != "") { + IoTItems.push_back((IoTItem *)new externalVariable("{\"id\":\"" + itemId + "_onError\",\"val\":\"" + msg + "\",\"int\":1}")); + generateEvent(itemId + "_onError", "1"); + } else { + IoTItems.push_back((IoTItem *)new externalVariable("{\"id\":\"onError\",\"val\":\"" + module + " " + msg + "\",\"int\":1}")); + generateEvent("onError", "1"); + } + } + if (isNetworkActive()) { if (jsonReadInt(settingsFlashJson, F("log")) != 0) { // String pl = "/log|" + tosend; diff --git a/src/utils/StringUtils.cpp b/src/utils/StringUtils.cpp index a8d4ee3b..eb869812 100644 --- a/src/utils/StringUtils.cpp +++ b/src/utils/StringUtils.cpp @@ -128,18 +128,18 @@ size_t itemsCount2(String str, const String& separator) { return cnt; } -size_t itemsCount(String& str, const char* delim) { - size_t cnt = 0; - char* cstr = new char[str.length() + 1]; - strcpy(cstr, str.c_str()); - char* token; - while ((token = strtok_r(cstr, delim, &cstr))) { - cnt++; - // printf("%s\n", token); - } - delete[] cstr; - return cnt; -} +// size_t itemsCount(String& str, const char* delim) { +// size_t cnt = 0; +// char* cstr = new char[str.length() + 1]; +// strcpy(cstr, str.c_str()); +// char* token; +// while ((token = strtok_r(cstr, delim, &cstr))) { +// cnt++; +// // printf("%s\n", token); +// } +// delete[] cstr; +// return cnt; +// } char* stringToChar(String& str) { char* mychar = new char[str.length() + 1]; @@ -198,3 +198,12 @@ String uint64ToString(uint64_t input, uint8_t base) { } while (input); return result; } + +String cleanString(String str) { + String clearStr = ""; + const String allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя.!-+ "; + for (size_t i = 0; i < str.length(); i++) { + if (allowedChars.indexOf(str.charAt(i)) != -1) clearStr += str.charAt(i); + } + return clearStr; +} \ No newline at end of file