Merge pull request #221 from biveraxe/ver4dev

Обновляем сетевые сценарии
This commit is contained in:
2022-10-30 12:14:36 +03:00
committed by GitHub
7 changed files with 62 additions and 24 deletions

View File

@@ -16,15 +16,19 @@ class IoTItem {
virtual void doByInterval(); virtual void doByInterval();
virtual IoTValue execute(String command, std::vector<IoTValue>& param); virtual IoTValue execute(String command, std::vector<IoTValue>& param);
void checkIntFromNet();
virtual void regEvent(const String& value, const String& consoleInfo, bool error = false, bool genEvent = true); 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); virtual void regEvent(float value, const String& consoleInfo, bool error = false, bool genEvent = true);
String getSubtype(); String getSubtype();
String getID(); String getID();
int getIntFromNet();
virtual String getValue(); virtual String getValue();
void setInterval(unsigned long interval); void setInterval(unsigned long interval);
void setIntFromNet(int interval);
unsigned long currentMillis; unsigned long currentMillis;
unsigned long prevMillis; unsigned long prevMillis;
@@ -54,6 +58,9 @@ class IoTItem {
String _subtype = ""; String _subtype = "";
String _id = ""; String _id = "";
unsigned long _interval = 1000; unsigned long _interval = 1000;
int _intFromNet = -2; // количество секунд доверия, пришедших из сети вместе с данными для текущего ИД
// -2 - данные не приходили, скорее всего, элемент локальный, доверие есть
// -1 - данные приходили и обратный отсчет дошел до нуля, значит доверия нет
float _multiply; // умножаем на значение float _multiply; // умножаем на значение
float _plus; // увеличиваем на значение float _plus; // увеличиваем на значение

View File

@@ -150,10 +150,17 @@ void loop() {
if (loopPeriod > 2) Serial.println(loopPeriod); if (loopPeriod > 2) Serial.println(loopPeriod);
#endif #endif
// сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение) if (millis()%1000 == 0) {
if (needSaveValues && millis()%1000 == 0) { // сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение)
syncValuesFlashJson(); if (needSaveValues) {
needSaveValues = false; syncValuesFlashJson();
needSaveValues = false;
}
// проверяем все элементы на тухлость
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
(*it)->checkIntFromNet();
}
} }
} }

View File

@@ -160,7 +160,6 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
//здесь мы получаем события с других устройств, которые потом проверяются в сценариях этого устройства //здесь мы получаем события с других устройств, которые потом проверяются в сценариях этого устройства
else if (topicStr.indexOf("event") != -1) { else if (topicStr.indexOf("event") != -1) {
//пока не работает сетевой обмен этот код будет закомментирован //пока не работает сетевой обмен этот код будет закомментирован
if (!jsonReadBool(settingsFlashJson, "mqttin")) { if (!jsonReadBool(settingsFlashJson, "mqttin")) {
return; return;
} }
@@ -174,24 +173,24 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
if (itemExist) { if (itemExist) {
unsigned long interval; unsigned long interval;
jsonRead(payloadStr, F("int"), interval); jsonRead(payloadStr, F("int"), interval);
itemExist->setInterval(interval); itemExist->setInterval(interval); // устанавливаем такой же интервал как на источнике события
itemExist->setValue(valAsStr, false); 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 { } else {
//добавим событие в базу // зафиксируем данные в базе, если локально элемент отсутствует
itemExist = (IoTItem*)new externalVariable(payloadStr); //itemExist = (IoTItem*)new externalVariable(payloadStr);
IoTItems.push_back(itemExist); //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) { else if (topicStr.indexOf("order") != -1) {
if (!jsonReadBool(settingsFlashJson, "mqttin")) { if (!jsonReadBool(settingsFlashJson, "mqttin")) {
return; return;

View File

@@ -98,7 +98,7 @@ void IoTItem::regEvent(const String& value, const String& consoleInfo, bool erro
String json = "{}"; String json = "{}";
jsonWriteStr_(json, "id", _id); jsonWriteStr_(json, "id", _id);
jsonWriteStr_(json, "val", value); jsonWriteStr_(json, "val", value);
jsonWriteInt_(json, "int", _interval/1000 + 5); // 5 секунд про запас jsonWriteInt_(json, "int", _interval/1000);
publishEvent(_id, json); publishEvent(_id, json);
SerialPrint("i", F("<=MQTT"), "Broadcast event: " + json); SerialPrint("i", F("<=MQTT"), "Broadcast event: " + json);
} }
@@ -137,6 +137,23 @@ String IoTItem::getSubtype() {
return _subtype; 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::publishValue() {}
void IoTItem::clearValue() {} void IoTItem::clearValue() {}

View File

@@ -286,6 +286,12 @@ class CallExprAST : public ExprAST {
if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе) if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе)
if (!Item) return nullptr; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим if (!Item) return nullptr; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим
if (Cmd == "getIntFromNet") {
ret.valD = Item->getIntFromNet();
ret.isDecimal = true;
return &ret;
}
// если все же все ок, то готовим параметры для передачи в модуль // если все же все ок, то готовим параметры для передачи в модуль
std::vector<IoTValue> ArgsAsIoTValue; std::vector<IoTValue> ArgsAsIoTValue;
for (unsigned int i = 0; i < Args.size(); i++) { for (unsigned int i = 0; i < Args.size(); i++) {

View File

@@ -29,12 +29,9 @@ class ButtonIn : public IoTItem {
if (_pinMode == "INPUT_PULLUP") IoTgpio.digitalWrite(_pin, HIGH); if (_pinMode == "INPUT_PULLUP") IoTgpio.digitalWrite(_pin, HIGH);
else if (_pinMode == "INPUT_PULLDOWN") IoTgpio.digitalWrite(_pin, LOW); else if (_pinMode == "INPUT_PULLDOWN") IoTgpio.digitalWrite(_pin, LOW);
// TODO: загрузить значение из памяти иначе пока просто считываем значение текущего состояния PIN
value.valD = _buttonState = IoTgpio.digitalRead(_pin); value.valD = _buttonState = IoTgpio.digitalRead(_pin);
// сообщаем всем о стартовом статусе без генерации события // сообщаем всем о стартовом статусе без генерации события
publishStatusMqtt(_id, (String)_buttonState); regEvent(_buttonState, "", false, false);
publishStatusWs(_id, (String)_buttonState);
} }
void loop() { void loop() {

View File

@@ -9,6 +9,11 @@
"title": "Сценарии", "title": "Сценарии",
"moduleDesc": "Сценарии позволяют реализовать индивидуальный алгоритм работы контроллера с учетом происходящих событий. Они представляют из себя описательный язык того, что нужно сделать при наступлении того или иного события, учитывая конкретные условия. \nВ базе языка - выражение вида: “Если условие истина, то выполнить одно действие, а если нет, то иное”. При этом проверка такого выражения будет осуществляться только при наступлении события связанного с элементом конфигурации, который упоминается в этом выражении. \nУсловием или действием может быть любое разрешенное выражение. Они все при выполнении возвращают значение. Выражение может состоять из: идентификаторов элементов конфигурации, чисел (целые, дробные и отрицательные), строк в кавычках, операций сравнения < > <= >= == !=, операций присваивания значений =, математических операций +-*/, логических операций &|, комментариев после символа #, функций (в параметрах которых так же могут быть любые разрешенные выражения), конструкции ветвления IfThenElse, группирующие блоки выражений {}", "moduleDesc": "Сценарии позволяют реализовать индивидуальный алгоритм работы контроллера с учетом происходящих событий. Они представляют из себя описательный язык того, что нужно сделать при наступлении того или иного события, учитывая конкретные условия. \nВ базе языка - выражение вида: “Если условие истина, то выполнить одно действие, а если нет, то иное”. При этом проверка такого выражения будет осуществляться только при наступлении события связанного с элементом конфигурации, который упоминается в этом выражении. \nУсловием или действием может быть любое разрешенное выражение. Они все при выполнении возвращают значение. Выражение может состоять из: идентификаторов элементов конфигурации, чисел (целые, дробные и отрицательные), строк в кавычках, операций сравнения < > <= >= == !=, операций присваивания значений =, математических операций +-*/, логических операций &|, комментариев после символа #, функций (в параметрах которых так же могут быть любые разрешенные выражения), конструкции ветвления IfThenElse, группирующие блоки выражений {}",
"funcInfo": [ "funcInfo": [
{
"name": "getIntFromNet",
"descr": "Получаем количество секунд доверия к значениям элемента. При -2 доверие полное, при -1 время доверия истекло. При >0 время обратного отсчета. Используется только совместно с ИД элемента: ID.getIntFromNet()",
"params": []
},
{ {
"name": "exit", "name": "exit",
"descr": "Прерываем работу сценария и выводим в консоль причину. Причина не обязательна.", "descr": "Прерываем работу сценария и выводим в консоль причину. Причина не обязательна.",