diff --git a/include/classes/IoTItem.h b/include/classes/IoTItem.h index ba2b1053..88162b28 100644 --- a/include/classes/IoTItem.h +++ b/include/classes/IoTItem.h @@ -16,15 +16,19 @@ class IoTItem { virtual void doByInterval(); virtual IoTValue execute(String command, std::vector& param); + void checkIntFromNet(); + virtual void regEvent(const String& value, const String& consoleInfo, bool error = false, bool genEvent = true); virtual void regEvent(float value, const String& consoleInfo, bool error = false, bool genEvent = true); String getSubtype(); String getID(); + int getIntFromNet(); virtual String getValue(); - + void setInterval(unsigned long interval); + void setIntFromNet(int interval); unsigned long currentMillis; unsigned long prevMillis; @@ -54,6 +58,9 @@ class IoTItem { String _subtype = ""; String _id = ""; unsigned long _interval = 1000; + int _intFromNet = -2; // количество секунд доверия, пришедших из сети вместе с данными для текущего ИД + // -2 - данные не приходили, скорее всего, элемент локальный, доверие есть + // -1 - данные приходили и обратный отсчет дошел до нуля, значит доверия нет float _multiply; // умножаем на значение float _plus; // увеличиваем на значение diff --git a/src/Main.cpp b/src/Main.cpp index bc5c2142..31cda3b5 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -150,10 +150,17 @@ void loop() { if (loopPeriod > 2) Serial.println(loopPeriod); #endif - // сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение) - if (needSaveValues && millis()%1000 == 0) { - syncValuesFlashJson(); - needSaveValues = false; + if (millis()%1000 == 0) { + // сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение) + if (needSaveValues) { + syncValuesFlashJson(); + needSaveValues = false; + } + + // проверяем все элементы на тухлость + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + (*it)->checkIntFromNet(); + } } } diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp index 72884352..3be1f3ef 100644 --- a/src/MqttClient.cpp +++ b/src/MqttClient.cpp @@ -160,7 +160,6 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) { //здесь мы получаем события с других устройств, которые потом проверяются в сценариях этого устройства else if (topicStr.indexOf("event") != -1) { //пока не работает сетевой обмен этот код будет закомментирован - if (!jsonReadBool(settingsFlashJson, "mqttin")) { return; } @@ -174,24 +173,24 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) { if (itemExist) { unsigned long interval; jsonRead(payloadStr, F("int"), interval); - itemExist->setInterval(interval); - itemExist->setValue(valAsStr, false); + itemExist->setInterval(interval); // устанавливаем такой же интервал как на источнике события + itemExist->setValue(valAsStr, false); // только регистрируем изменения в интерфейсе без создания цикла сетевых событий + if (interval) itemExist->setIntFromNet(interval+5); // если пришедший интервал =0, значит не нужно контролировать доверие, иначе даем фору в 5 сек + + // запустим проверку его в сценариях + generateEvent(id, valAsStr); + SerialPrint("i", F("=>MQTT"), "Received event from other device: '" + devId + "' " + id + " " + valAsStr); } else { - //добавим событие в базу - itemExist = (IoTItem*)new externalVariable(payloadStr); - IoTItems.push_back(itemExist); + // зафиксируем данные в базе, если локально элемент отсутствует + //itemExist = (IoTItem*)new externalVariable(payloadStr); + //IoTItems.push_back(itemExist); } - //запустим проверку его в сценариях - generateEvent(id, valAsStr); - publishStatusMqtt(id, valAsStr); - publishStatusWs(id, valAsStr); - //itemExist->regEvent(valAsStr, ""); - SerialPrint("i", F("=>MQTT"), "Received event from other device: '" + devId + "' " + id + " " + valAsStr); + } } - //здесь мы получаем прямые команды которые сразу выполнятся на этом устройстве - //необходимо для тех кто хочет управлять своим устройством из mqtt + // здесь мы получаем прямые команды которые сразу выполнятся на этом устройстве + // необходимо для тех кто хочет управлять своим устройством из mqtt else if (topicStr.indexOf("order") != -1) { if (!jsonReadBool(settingsFlashJson, "mqttin")) { return; diff --git a/src/classes/IoTItem.cpp b/src/classes/IoTItem.cpp index e78e6b42..65a03392 100644 --- a/src/classes/IoTItem.cpp +++ b/src/classes/IoTItem.cpp @@ -98,7 +98,7 @@ void IoTItem::regEvent(const String& value, const String& consoleInfo, bool erro String json = "{}"; jsonWriteStr_(json, "id", _id); jsonWriteStr_(json, "val", value); - jsonWriteInt_(json, "int", _interval/1000 + 5); // 5 секунд про запас + jsonWriteInt_(json, "int", _interval/1000); publishEvent(_id, json); SerialPrint("i", F("<=MQTT"), "Broadcast event: " + json); } @@ -137,6 +137,23 @@ String IoTItem::getSubtype() { return _subtype; } +int IoTItem::getIntFromNet() { + return _intFromNet; +} + +void IoTItem::setIntFromNet(int interval) { + _intFromNet = interval; +} + +void IoTItem::checkIntFromNet() { + if (_intFromNet >= 0) { + if (_intFromNet == 0) { + SerialPrint("E", "SYS", "The new data did not come from the network. The level of trust is low.", _id); + } + _intFromNet--; + } +} + void IoTItem::publishValue() {} void IoTItem::clearValue() {} diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 93534041..e4c59e25 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -286,6 +286,12 @@ class CallExprAST : public ExprAST { if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе) if (!Item) return nullptr; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим + if (Cmd == "getIntFromNet") { + ret.valD = Item->getIntFromNet(); + ret.isDecimal = true; + return &ret; + } + // если все же все ок, то готовим параметры для передачи в модуль std::vector ArgsAsIoTValue; for (unsigned int i = 0; i < Args.size(); i++) { diff --git a/src/modules/sceninfo.json b/src/modules/sceninfo.json index 6f26cc47..fb472e38 100644 --- a/src/modules/sceninfo.json +++ b/src/modules/sceninfo.json @@ -9,6 +9,11 @@ "title": "Сценарии", "moduleDesc": "Сценарии позволяют реализовать индивидуальный алгоритм работы контроллера с учетом происходящих событий. Они представляют из себя описательный язык того, что нужно сделать при наступлении того или иного события, учитывая конкретные условия. \nВ базе языка - выражение вида: “Если условие истина, то выполнить одно действие, а если нет, то иное”. При этом проверка такого выражения будет осуществляться только при наступлении события связанного с элементом конфигурации, который упоминается в этом выражении. \nУсловием или действием может быть любое разрешенное выражение. Они все при выполнении возвращают значение. Выражение может состоять из: идентификаторов элементов конфигурации, чисел (целые, дробные и отрицательные), строк в кавычках, операций сравнения < > <= >= == !=, операций присваивания значений =, математических операций +-*/, логических операций &|, комментариев после символа #, функций (в параметрах которых так же могут быть любые разрешенные выражения), конструкции ветвления IfThenElse, группирующие блоки выражений {}", "funcInfo": [ + { + "name": "getIntFromNet", + "descr": "Получаем количество секунд доверия к значениям элемента. При -2 доверие полное, при -1 время доверия истекло. При >0 время обратного отсчета. Используется только совместно с ИД элемента: ID.getIntFromNet()", + "params": [] + }, { "name": "exit", "descr": "Прерываем работу сценария и выводим в консоль причину. Причина не обязательна.",