From 80607c593b3ccb62d2676cc8ef638e19f22d0ae7 Mon Sep 17 00:00:00 2001 From: biver Date: Sat, 3 Sep 2022 21:31:52 +0300 Subject: [PATCH 1/6] =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=88=D0=B8=D1=80=D1=8F?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E=20=D0=BE=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/virtual/Timer/modinfo.json | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/modules/virtual/Timer/modinfo.json b/src/modules/virtual/Timer/modinfo.json index f2256166..6d4bb7b4 100644 --- a/src/modules/virtual/Timer/modinfo.json +++ b/src/modules/virtual/Timer/modinfo.json @@ -27,11 +27,33 @@ "moduleDesc": "Добавляет инструмент таймеров обратного отсчета для организации периодичных операций или логических конструкций. Часто используется как вспомогательный элемент для автоматизации.", "propInfo": { "int": "Задает размер в секундах одного шага(тика) таймера.", - "countDown": "Начальное значение таймера, с которого начинается обратный отсчет.", + "countDown": "Начальное значение таймера, с которого начинается обратный отсчет. countDown=0 - бесконечный счет (имеет смысл при ticker=1, иначе таймер будет выключен), countDown=-1 - отключает таймер совсем (используется для запуска системы с выключенным таймером)", "ticker": "Генерировать(1) или нет(0) события при каждом тике таймера.", "repeat": "Сбрасывать(1) или нет(0) таймер в начальное состояние при достижении нуля.", "needSave": "Требуется сохранять(1) или нет(0) состояние в энерго независимую память. Функция находится в разработке." - } + }, + "funcInfo": [ + { + "name": "stop", + "descr": "Поставить процесс на паузу, при этом не будет событий и не будет уменьшаться счетчик.", + "params": [] + }, + { + "name": "reset", + "descr": "Вернуть таймер к началу, установленному в countDown.", + "params": [] + }, + { + "name": "continue", + "descr": "Продолжить выполнение с момента остановки.", + "params": [] + }, + { + "name": "int", + "descr": "Можно изменить шаг тиков.", + "params": [] + } + ] }, "defActive": true, "devices": { From a010859c0684480b3730df50781d5b55f683491f Mon Sep 17 00:00:00 2001 From: biver Date: Sat, 3 Sep 2022 21:32:39 +0300 Subject: [PATCH 2/6] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D1=8F=D0=B5=D0=BC=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D1=81=D0=B8=D0=BD=D1=82=D0=B0=D0=BA=D1=81=D0=B8=D1=81?= =?UTF-8?q?=D0=B5=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=B2=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=98=D0=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/classes/IoTScenario.h | 12 +++---- src/classes/IoTScenario.cpp | 68 ++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index ec0dc516..7a1630df 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -47,16 +47,16 @@ class IoTScenario { /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' - ExprAST *ParseIdentifierExpr(String *IDNames); + ExprAST *ParseIdentifierExpr(String *IDNames, bool callFromCondition); /// numberexpr ::= number ExprAST *ParseNumberExpr(); /// parenexpr ::= '(' expression ')' - ExprAST *ParseParenExpr(); + ExprAST *ParseParenExpr(String *IDNames, bool callFromCondition); /// bracketsexpr ::= '{' expression '}' - ExprAST *ParseBracketsExpr(); + ExprAST *ParseBracketsExpr(String *IDNames, bool callFromCondition); /// quotesexpr ::= '"' expression '"' ExprAST *ParseQuotesExpr(); @@ -68,16 +68,16 @@ class IoTScenario { /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr - ExprAST *ParsePrimary(String *IDNames); + ExprAST *ParsePrimary(String *IDNames, bool callFromCondition); /// binoprhs /// ::= ('+' primary)* - ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames); + ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames, bool callFromCondition); /// expression /// ::= primary binoprhs /// - ExprAST *ParseExpression(String *IDNames); + ExprAST *ParseExpression(String *IDNames, bool callFromCondition); int getLastChar(); fs::File file; diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 4e9b9284..3b63663d 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -728,7 +728,7 @@ ExprAST *IoTScenario::Error(const char *Str) { /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' -ExprAST *IoTScenario::ParseIdentifierExpr(String *IDNames) { +ExprAST *IoTScenario::ParseIdentifierExpr(String *IDNames, bool callFromCondition) { String IdName = IdentifierStr; String Cmd = ""; IoTItem *tmpItem = findIoTItem(IdName); @@ -754,7 +754,7 @@ ExprAST *IoTScenario::ParseIdentifierExpr(String *IDNames) { std::vector Args; if (CurTok != ')') { while (1) { - ExprAST *Arg = ParseExpression(IDNames); + ExprAST *Arg = ParseExpression(IDNames, callFromCondition); if (!Arg) return nullptr; Args.push_back(Arg); @@ -783,9 +783,9 @@ ExprAST *IoTScenario::ParseNumberExpr() { } /// parenexpr ::= '(' expression ')' -ExprAST *IoTScenario::ParseParenExpr() { +ExprAST *IoTScenario::ParseParenExpr(String *IDNames, bool callFromCondition) { getNextToken(); // получаем (. - ExprAST *V = ParseExpression(nullptr); + ExprAST *V = ParseExpression(IDNames, callFromCondition); if (!V) return nullptr; if (CurTok != ')') @@ -795,28 +795,31 @@ ExprAST *IoTScenario::ParseParenExpr() { } /// bracketsexpr ::= '{' expression '}' -ExprAST *IoTScenario::ParseBracketsExpr() { +ExprAST *IoTScenario::ParseBracketsExpr(String *IDNames, bool callFromCondition) { getNextToken(); // получаем {. std::vector bracketsList; - if (CurTok != '}') { - while (1) { - ExprAST *Expr = ParseExpression(nullptr); + + while (CurTok != '}') { + ExprAST *Expr = ParseExpression(IDNames, callFromCondition); if (!Expr) return nullptr; bracketsList.push_back(Expr); + + //if (CurTok == '}') break; - if (CurTok != ';') - return Error("Expected ';' in operation list"); - int ttok = getNextToken(); - if (!ttok) { - Error("Expected '}'"); - break; - } + Serial.printf("ParseBracketsExpr CurTok = %d \n", CurTok); - if (CurTok == '}') break; + + + //if (CurTok != ';') + // return Error("Expected ';' in operation list"); + + //int ttok = getNextToken(); + if (CurTok == tok_eof) { + return Error("Expected '}'"); + } } - } - //getNextToken(); // получаем }. + getNextToken(); // получаем }. return new BracketsExprAST(bracketsList); } @@ -833,14 +836,14 @@ ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { getNextToken(); // Получаем if. // условие. - ExprAST *Cond = ParseExpression(IDNames); + ExprAST *Cond = ParseExpression(IDNames, true); if (!Cond) return nullptr; if (CurTok != tok_then) return Error("expected then"); getNextToken(); // Получаем then - ExprAST *Then = ParseExpression(nullptr); + ExprAST *Then = ParseExpression(IDNames, false); if (!Then) return nullptr; // if (CurTok != tok_else) @@ -848,7 +851,8 @@ ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { ExprAST *Else = nullptr; if (CurTok == tok_else) { getNextToken(); - Else = ParseExpression(nullptr); + Else = ParseExpression(IDNames, false); + if (!Else) return nullptr; } return new IfExprAST(Cond, Then, Else, IDNames); @@ -858,24 +862,24 @@ ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr -ExprAST *IoTScenario::ParsePrimary(String *IDNames) { +ExprAST *IoTScenario::ParsePrimary(String *IDNames, bool callFromCondition) { switch (CurTok) { default: Serial.println(CurTok); return Error("unknown token when expecting an expression"); case tok_identifier: { - if (IDNames) { + if (callFromCondition && IDNames) { String tmpstr = *IDNames; *IDNames = tmpstr + " " + IdentifierStr + " "; } - return ParseIdentifierExpr(IDNames); + return ParseIdentifierExpr(IDNames, callFromCondition); } case tok_number: return ParseNumberExpr(); case '(': - return ParseParenExpr(); + return ParseParenExpr(IDNames, callFromCondition); case '{': - return ParseBracketsExpr(); + return ParseBracketsExpr(IDNames, callFromCondition); case tok_string: return ParseQuotesExpr(); case tok_if: @@ -885,7 +889,7 @@ ExprAST *IoTScenario::ParsePrimary(String *IDNames) { /// binoprhs /// ::= ('+' primary)* -ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) { +ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames, bool callFromCondition) { // Если это бинарный оператор, получаем его приоритет while (1) { int TokPrec = GetTokPrecedence(); @@ -900,14 +904,14 @@ ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) getNextToken(); // eat binop // Разобрать первичное выражение после бинарного оператора - ExprAST *RHS = ParsePrimary(IDNames); + ExprAST *RHS = ParsePrimary(IDNames, callFromCondition); if (!RHS) return nullptr; // Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS, // то берём часть вместе с RHS как LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec + 1, RHS, IDNames); + RHS = ParseBinOpRHS(TokPrec + 1, RHS, IDNames, callFromCondition); if (RHS == nullptr) return nullptr; } @@ -919,10 +923,10 @@ ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) /// expression /// ::= primary binoprhs /// -ExprAST *IoTScenario::ParseExpression(String *IDNames) { - ExprAST *LHS = ParsePrimary(IDNames); +ExprAST *IoTScenario::ParseExpression(String *IDNames, bool callFromCondition) { + ExprAST *LHS = ParsePrimary(IDNames, callFromCondition); if (!LHS) return nullptr; - return ParseBinOpRHS(0, LHS, IDNames); + return ParseBinOpRHS(0, LHS, IDNames, callFromCondition); } From 9403a150ffbd99ee324351b16e61e0705626cd8d Mon Sep 17 00:00:00 2001 From: biver Date: Sun, 4 Sep 2022 09:01:47 +0300 Subject: [PATCH 3/6] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=89?= =?UTF-8?q?=D0=B0=D0=B5=D0=BC=20;=20=D0=B2=20=D1=81=D1=86=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=D1=80=D0=B8=D0=B8=20=D0=BA=D0=B0=D0=BA=20=D0=BD=D0=B5?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D1=87=D0=B0=D1=89=D0=B8=D0=B9=20=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=B2=D0=BE=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WsServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 5d3b0ba1..47dab0cd 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -98,6 +98,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) strFromFile.replace("{\"scen\":\"", ""); strFromFile.replace("\\n", "\n"); strFromFile.replace("\\\"", "\""); + strFromFile.replace(";", " "); strFromFile.remove(strFromFile.length() - 2, 2); } myfile.close(); From ed2eb6cfb7c176104c31872c2d4a7f765faf1939 Mon Sep 17 00:00:00 2001 From: biver Date: Sun, 4 Sep 2022 11:20:33 +0300 Subject: [PATCH 4/6] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D1=8F=D0=B5=D0=BC=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D1=83=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B1=D0=BE=D1=80=D0=B0=20=D0=BA=D0=BE?= =?UTF-8?q?=D1=80=D0=BD=D0=B5=D0=B2=D1=8B=D1=85=20=D0=98=D0=A4=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B8=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=B8=D0=BC=20=D0=BC?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/classes/IoTScenario.h | 9 +++++++ src/classes/IoTScenario.cpp | 49 +++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index 7a1630df..f212bb8a 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -12,6 +12,15 @@ class ExprAST { }; class IoTScenario { + int mode = 0; // режим работы: + // 0 - весь сценарий хранится в FS, читаем посимвольно из файла. Максимальная экономии памяти, но медленно + // 1 - весь сценарий подгружается в String, читаем посимвольно из строки + // 2 - сценарий конвертируется в структуру классов за один проход и выполняется только в памяти. Максимальная + // скорость, но на 8266 при средних сценариях не хватает памяти + + String strFromFile; + int charCount; + //===----------------------------------------------------------------------===// // Lexer (Лексический анализатор) //===----------------------------------------------------------------------===// diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 3b63663d..dd7aad59 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -933,33 +933,44 @@ ExprAST *IoTScenario::ParseExpression(String *IDNames, bool callFromCondition) { void IoTScenario::loadScenario(String fileName) { // подготавливаем контекст для чтения и интерпретации файла if (file) file.close(); file = FileFS.open(fileName, "r"); -} - -void IoTScenario::exec(String eventIdName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST if (!file) { Error("Open file scenario error"); return; } + + if (mode == 1) { + strFromFile = file.readString(); + file.close(); + } +} + +void IoTScenario::exec(String eventIdName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST + if (mode == 0 && !file) return; + LastChar = 0; CurTok = 0; - file.seek(0); curLine = 1; - - while ((getNextToken()) != EOF) { - switch (CurTok) { - case tok_if: { - IDNames = ""; // сбрасываем накопитель встречающихся идентификаторов в условии - ExprAST *tmpAST = ParseIfExpr(&IDNames); - if (!tmpAST) { - Error("IF Expr wrong."); - break; - } - if (tmpAST->hasEventIdName(eventIdName)) { - tmpAST->exec(); - } - delete tmpAST; - break;} + if (mode == 0) file.seek(0); else charCount = 0; + + if (mode < 2) { + while (CurTok != EOF) { + switch (CurTok) { + case tok_if: { + IDNames = ""; // сбрасываем накопитель встречающихся идентификаторов в условии + ExprAST *tmpAST = ParseIfExpr(&IDNames); + if (!tmpAST) { + Error("IF Expr wrong."); + break; + } + + if (tmpAST->hasEventIdName(eventIdName)) { + tmpAST->exec(); + } + delete tmpAST; + break;} + default: getNextToken(); break; + } } } } From 0d7304e297461ff64f8f1b5b8a49c73673717dc5 Mon Sep 17 00:00:00 2001 From: biver Date: Sun, 4 Sep 2022 19:16:08 +0300 Subject: [PATCH 5/6] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D0=BC=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=20=D1=87=D1=82?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=86=D0=B5=D0=BD=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B8=D0=B7=20String?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/IoTScenario.cpp | 48 +++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index dd7aad59..e66d7a64 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -586,11 +586,22 @@ class BracketsExprAST : public ExprAST { //===----------------------------------------------------------------------===// int IoTScenario::getLastChar() { - if (file) { - LastChar = file.read(); - if (LastChar == 10) curLine++; - return LastChar; - } else return EOF; + if (mode == 0) { + if (file) { + LastChar = file.read(); + if (LastChar == 10) curLine++; + return LastChar; + } else return EOF; + } else if (mode == 1) { + if (charCount < strFromFile.length()) { + LastChar = strFromFile.charAt(charCount); + //Serial.printf("%d, ", LastChar); + if (LastChar == 10) curLine++; + charCount++; + return LastChar; + } else return EOF; + } + } /// gettok - Возвращает следующий токен из стандартного потока ввода. @@ -806,7 +817,7 @@ ExprAST *IoTScenario::ParseBracketsExpr(String *IDNames, bool callFromCondition) //if (CurTok == '}') break; - Serial.printf("ParseBracketsExpr CurTok = %d \n", CurTok); + //Serial.printf("ParseBracketsExpr CurTok = %d \n", CurTok); @@ -931,15 +942,21 @@ ExprAST *IoTScenario::ParseExpression(String *IDNames, bool callFromCondition) { void IoTScenario::loadScenario(String fileName) { // подготавливаем контекст для чтения и интерпретации файла - if (file) file.close(); - file = FileFS.open(fileName, "r"); - if (!file) { - Error("Open file scenario error"); - return; - } - - if (mode == 1) { + if (mode == 0) { + if (file) file.close(); + file = FileFS.open(fileName.c_str(), "r"); + if (!file) { + Error("Open file scenario error"); + return; + } + } else if (mode == 1) { + file = FileFS.open(fileName.c_str(), "r"); + if (!file) { + Error("Open file scenario error"); + return; + } strFromFile = file.readString(); + Serial.printf("strFromFile: %s, %s\n", strFromFile.c_str(), fileName.c_str()); file.close(); } } @@ -950,8 +967,9 @@ void IoTScenario::exec(String eventIdName) { // посимвольно счит LastChar = 0; CurTok = 0; curLine = 1; + charCount = 0; - if (mode == 0) file.seek(0); else charCount = 0; + if (mode == 0) file.seek(0); if (mode < 2) { while (CurTok != EOF) { From 03bc6560849f026450ef5688d181aa83d5e13bea Mon Sep 17 00:00:00 2001 From: biver Date: Sun, 4 Sep 2022 23:37:29 +0300 Subject: [PATCH 6/6] =?UTF-8?q?=D0=9F=D0=BE=D0=BD=D0=B8=D0=BC=D0=B0=D0=B5?= =?UTF-8?q?=D0=BC=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D1=82=D0=B0?= =?UTF-8?q?=D0=B1=D1=8B=20=D0=B2=20=D1=81=D1=86=D0=B5=D0=BD=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D1=8F=D1=85=20=D0=B8=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WsServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 47dab0cd..98b60aba 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -99,6 +99,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) strFromFile.replace("\\n", "\n"); strFromFile.replace("\\\"", "\""); strFromFile.replace(";", " "); + strFromFile.replace("\\t", " "); strFromFile.remove(strFromFile.length() - 2, 2); } myfile.close();