From 0f869ebf39828abd1fd31e2a29c4342633a9e0ac Mon Sep 17 00:00:00 2001 From: biver Date: Mon, 29 Aug 2022 00:45:55 +0300 Subject: [PATCH 1/3] =?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=D0=BF=D0=BE=D0=B1=D0=BB=D0=BE=D1=87=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D1=83=20?= =?UTF-8?q?=D1=81=D1=86=D0=B5=D0=BD=D0=B0=D1=80=D0=B8=D0=B5=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Const.h | 3 +++ include/classes/IoTScenario.h | 4 +-- src/EventsAndOrders.cpp | 4 ++- src/Main.cpp | 3 ++- src/WsServer.cpp | 2 +- src/classes/IoTScenario.cpp | 49 +++++++++++++++++++++-------------- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/include/Const.h b/include/Const.h index ed2e43ae..d8e60889 100644 --- a/include/Const.h +++ b/include/Const.h @@ -3,6 +3,9 @@ //Версия прошивки #define FIRMWARE_VERSION 412 +//Поблочная загрузка сценариев =1 грузим блоками, =0 грузим и держим в памяти весь сценарий +#define SCENARIO_BLOCK_LOAD 1 + #ifdef esp8266_4mb #define FIRMWARE_NAME "esp8266_4mb" #endif diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index 6308fd26..26a50b9d 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -86,8 +86,8 @@ class IoTScenario { void clearScenarioElements(); public: - void loadScenario(String fileName); - void ExecScenario(String eventIdName); + void loadScenario(String fileName, String eventIdName); + void execScenario(String eventIdName); IoTScenario(); ~IoTScenario(); diff --git a/src/EventsAndOrders.cpp b/src/EventsAndOrders.cpp index 1733ed86..b63a461d 100644 --- a/src/EventsAndOrders.cpp +++ b/src/EventsAndOrders.cpp @@ -52,7 +52,9 @@ void handleEvent() { //здесь нужно пропускать данное событие через условия сценариев //и если оно есть в условии сценария и совподает - iotScen.ExecScenario(selectToMarker(event, " ")); + String tmpStr = selectToMarker(event, " "); + if (SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", tmpStr); + else iotScen.execScenario(tmpStr); eventBuf = deleteBeforeDelimiter(eventBuf, ","); } diff --git a/src/Main.cpp b/src/Main.cpp index 437a4f6f..b8e82403 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -64,7 +64,8 @@ void setup() { asyncUdpInit(); //загрузка сценария - iotScen.loadScenario("/scenario.json"); + if (!SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", ""); + // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem *)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 9c48b5c3..cc9a6c2b 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -77,7 +77,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) writeFileUint8tByFrames("scenario.json", payload, length, headerLenth, 256); clearConfigure(); configure("/config.json"); - iotScen.loadScenario("/scenario.json"); + if (!SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", ""); // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 69ae8e7a..3bf6bbaf 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -747,7 +747,7 @@ ExprAST *IoTScenario::ParseIdentifierExpr(String *IDNames) { if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(IDNames); - if (!Arg) return 0; + if (!Arg) return nullptr; Args.push_back(Arg); if (CurTok == ')') break; @@ -778,7 +778,7 @@ ExprAST *IoTScenario::ParseNumberExpr() { ExprAST *IoTScenario::ParseParenExpr() { getNextToken(); // получаем (. ExprAST *V = ParseExpression(nullptr); - if (!V) return 0; + if (!V) return nullptr; if (CurTok != ')') return Error("expected ')'"); @@ -793,7 +793,7 @@ ExprAST *IoTScenario::ParseBracketsExpr() { if (CurTok != '}') { while (1) { ExprAST *Expr = ParseExpression(nullptr); - if (!Expr) return 0; + if (!Expr) return nullptr; bracketsList.push_back(Expr); if (CurTok != ';') @@ -826,14 +826,14 @@ ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { // условие. ExprAST *Cond = ParseExpression(IDNames); - if (!Cond) return 0; + if (!Cond) return nullptr; if (CurTok != tok_then) return Error("expected then"); getNextToken(); // Получаем then ExprAST *Then = ParseExpression(nullptr); - if (!Then) return 0; + if (!Then) return nullptr; // if (CurTok != tok_else) // return Error("expected else"); @@ -892,14 +892,14 @@ ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) // Разобрать первичное выражение после бинарного оператора ExprAST *RHS = ParsePrimary(IDNames); - if (!RHS) return 0; + if (!RHS) return nullptr; // Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS, // то берём часть вместе с RHS как LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec + 1, RHS, IDNames); - if (RHS == 0) return 0; + if (RHS == nullptr) return nullptr; } // Собираем LHS/RHS. @@ -912,7 +912,7 @@ ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) /// ExprAST *IoTScenario::ParseExpression(String *IDNames) { ExprAST *LHS = ParsePrimary(IDNames); - if (!LHS) return 0; + if (!LHS) return nullptr; return ParseBinOpRHS(0, LHS, IDNames); } @@ -923,31 +923,42 @@ void IoTScenario::clearScenarioElements() { // удаляем все корне ScenarioElements.clear(); } -void IoTScenario::loadScenario(String fileName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST - clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых. +void IoTScenario::loadScenario(String fileName, String eventIdName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST + if (!SCENARIO_BLOCK_LOAD) clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых. LastChar = ' '; File myfile = seekFile(fileName); if (myfile.available()) { strFromFile = new String(""); - String strFromF = myfile.readString(); - Serial.println(strFromF); - jsonRead(strFromF, "scen", *strFromFile, true); + *strFromFile = myfile.readString(); + //Serial.println(strFromF); + //jsonRead(strFromF, "scen", *strFromFile, true); myfile.close(); - // Serial.println(*strFromFile); + strFromFile->replace("{\"scen\":\"", ""); + //strFromFile->replace("\"}", ""); + //Serial.println(*strFromFile); if (strFromFile->length()) { getNextToken(); while (strIterator < strFromFile->length() - 1) { // Serial.printf("-%c", LastChar); switch (CurTok) { - // case tok_eof: return; - // case ';': getNextToken(); break; // игнорируем верхнеуровневые точки с запятой. + // case tok_eof: break; case tok_if: { String IDNames = ""; // накопитель встречающихся идентификаторов в условии - ScenarioElements.push_back(ParseIfExpr(&IDNames)); + ExprAST *tmpAST = ParseIfExpr(&IDNames); + if (!tmpAST) break; + + if (SCENARIO_BLOCK_LOAD) { + if (tmpAST->hasEventIdName(eventIdName)) { + tmpAST->exec(); + Serial.println("Exec from loadIF"); + } + delete tmpAST; + } else ScenarioElements.push_back(tmpAST); + break; } default: @@ -964,10 +975,10 @@ void IoTScenario::loadScenario(String fileName) { // посимвольно с } } -void IoTScenario::ExecScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы +void IoTScenario::execScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы // eventIdName - ID элемента для которого выполняем сценарий, т.е. игнорируем любые проверки, если нет такого ID в условиях isIotScenException = false; - // Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); + //Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); for (unsigned int i = 0; i < ScenarioElements.size(); i++) { if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); // else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); From e17260628ea367c2361617f1ea4c947ae40e164e Mon Sep 17 00:00:00 2001 From: biver Date: Mon, 29 Aug 2022 16:01:25 +0300 Subject: [PATCH 2/3] strFromFile --- include/classes/IoTScenario.h | 2 +- src/classes/IoTScenario.cpp | 40 ++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index 26a50b9d..22aab25a 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -79,7 +79,7 @@ class IoTScenario { std::vector ScenarioElements; // корневые элементы дерава - String *strFromFile; + String strFromFile; char getLastChar(); int strIterator = 0; diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 3bf6bbaf..04527a3f 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -587,8 +587,10 @@ class BracketsExprAST : public ExprAST { //===----------------------------------------------------------------------===// char IoTScenario::getLastChar() { + if (strIterator == strFromFile.length()) return 0; + char tmpCh = strFromFile.charAt(strIterator); strIterator++; - return strFromFile->charAt(strIterator - 1); + return tmpCh; } /// gettok - Возвращает следующий токен из стандартного потока ввода. @@ -625,7 +627,7 @@ int IoTScenario::gettok() { if (LastChar == '#') { // Комментарий до конца строки do LastChar = getLastChar(); - while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + while (LastChar != 0 && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); @@ -634,7 +636,7 @@ int IoTScenario::gettok() { if (LastChar == '"') { // "строка" IdentifierStr = ""; LastChar = getLastChar(); - while (LastChar != '"') { + while (LastChar != '"' && LastChar != 0) { IdentifierStr += LastChar; LastChar = getLastChar(); } @@ -853,6 +855,7 @@ ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { ExprAST *IoTScenario::ParsePrimary(String *IDNames) { switch (CurTok) { default: + Serial.println(CurTok); return Error("unknown token when expecting an expression"); case tok_identifier: { if (IDNames) { @@ -929,28 +932,31 @@ void IoTScenario::loadScenario(String fileName, String eventIdName) { // пос File myfile = seekFile(fileName); if (myfile.available()) { - strFromFile = new String(""); + //strFromFile = new String(""); - *strFromFile = myfile.readString(); + strFromFile = myfile.readString(); //Serial.println(strFromF); //jsonRead(strFromF, "scen", *strFromFile, true); myfile.close(); - strFromFile->replace("{\"scen\":\"", ""); - //strFromFile->replace("\"}", ""); - //Serial.println(*strFromFile); + strFromFile.replace("{\"scen\":\"", ""); + strFromFile.replace("\\n\"}", ""); + strFromFile.replace("\\n", "\n"); + strFromFile.replace("\\\"", "\""); + //Serial.println(strFromFile); - if (strFromFile->length()) { - getNextToken(); - while (strIterator < strFromFile->length() - 1) { + if (strFromFile.length()) { + + while (strIterator < strFromFile.length()) { // Serial.printf("-%c", LastChar); + getNextToken(); switch (CurTok) { // case tok_eof: break; case tok_if: { String IDNames = ""; // накопитель встречающихся идентификаторов в условии ExprAST *tmpAST = ParseIfExpr(&IDNames); if (!tmpAST) break; - + if (SCENARIO_BLOCK_LOAD) { if (tmpAST->hasEventIdName(eventIdName)) { tmpAST->exec(); @@ -958,17 +964,17 @@ void IoTScenario::loadScenario(String fileName, String eventIdName) { // пос } delete tmpAST; } else ScenarioElements.push_back(tmpAST); - - break; + break; } + default: - getNextToken(); - break; + + break; } } } - delete strFromFile; + //delete strFromFile; strIterator = 0; } else { Error("Open file scenario error"); From 52f6877ef7e4895b8f271114dbe427122f174e1c Mon Sep 17 00:00:00 2001 From: biver Date: Tue, 30 Aug 2022 14:00:22 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D0=A7=D0=B8=D1=82=D0=B0=D0=B5=D0=BC=20?= =?UTF-8?q?=D1=81=D1=86=D0=B5=D0=BD=D0=B0=D1=80=D0=B8=D0=B9=20=D0=B8=D0=B7?= =?UTF-8?q?=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_svelte/scenario.txt | 0 include/Const.h | 3 - include/classes/IoTScenario.h | 16 ++--- src/EventsAndOrders.cpp | 4 +- src/Main.cpp | 6 +- src/WsServer.cpp | 17 ++++- src/classes/IoTScenario.cpp | 124 +++++++++++----------------------- 7 files changed, 67 insertions(+), 103 deletions(-) create mode 100644 data_svelte/scenario.txt diff --git a/data_svelte/scenario.txt b/data_svelte/scenario.txt new file mode 100644 index 00000000..e69de29b diff --git a/include/Const.h b/include/Const.h index b8be0285..dad350c6 100644 --- a/include/Const.h +++ b/include/Const.h @@ -3,9 +3,6 @@ //Версия прошивки #define FIRMWARE_VERSION 413 -//Поблочная загрузка сценариев =1 грузим блоками, =0 грузим и держим в памяти весь сценарий -#define SCENARIO_BLOCK_LOAD 1 - #ifdef esp8266_4mb #define FIRMWARE_NAME "esp8266_4mb" #endif diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index 22aab25a..b717c0e7 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -18,7 +18,7 @@ class IoTScenario { String IdentifierStr; // Заполняется, если tok_identifier float NumVal; // Заполняется, если tok_number - char LastChar = ' '; + int LastChar; /// gettok - Возвращает следующий токен из стандартного потока ввода. int gettok(); @@ -32,6 +32,7 @@ class IoTScenario { /// лексического анализатора и обновляет CurTok. int CurTok; int getNextToken(); + String IDNames; // накопитель встречающихся идентификаторов в условии /// BinopPrecedence - Содержит приоритеты для бинарных операторов std::map BinopPrecedence; @@ -77,17 +78,12 @@ class IoTScenario { /// ExprAST *ParseExpression(String *IDNames); - std::vector ScenarioElements; // корневые элементы дерава - - String strFromFile; - char getLastChar(); - int strIterator = 0; - - void clearScenarioElements(); + int getLastChar(); + fs::File file; public: - void loadScenario(String fileName, String eventIdName); - void execScenario(String eventIdName); + void loadScenario(String fileName); + void exec(String eventIdName); IoTScenario(); ~IoTScenario(); diff --git a/src/EventsAndOrders.cpp b/src/EventsAndOrders.cpp index b63a461d..bffbbc4c 100644 --- a/src/EventsAndOrders.cpp +++ b/src/EventsAndOrders.cpp @@ -52,9 +52,7 @@ void handleEvent() { //здесь нужно пропускать данное событие через условия сценариев //и если оно есть в условии сценария и совподает - String tmpStr = selectToMarker(event, " "); - if (SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", tmpStr); - else iotScen.execScenario(tmpStr); + iotScen.exec(selectToMarker(event, " ")); eventBuf = deleteBeforeDelimiter(eventBuf, ","); } diff --git a/src/Main.cpp b/src/Main.cpp index b8e82403..102995e1 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -62,10 +62,10 @@ void setup() { //запуск работы udp asyncUdpInit(); - - //загрузка сценария - if (!SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", ""); + //подготавливаем сценарии + iotScen.loadScenario("/scenario.txt"); + // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem *)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/WsServer.cpp b/src/WsServer.cpp index cc9a6c2b..40ba0d07 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -75,9 +75,24 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) } if (headerStr == "/oiranecs|") { writeFileUint8tByFrames("scenario.json", payload, length, headerLenth, 256); + + String strFromFile; + File myfile = seekFile("/scenario.json"); + if (myfile.available()) { + strFromFile = myfile.readString(); + + strFromFile.replace("{\"scen\":\"", ""); + strFromFile.replace("\\n", "\n"); + strFromFile.replace("\\\"", "\""); + strFromFile.remove(strFromFile.length() - 2, 2); + } + myfile.close(); + + writeFile("/scenario.txt", strFromFile); + clearConfigure(); configure("/config.json"); - if (!SCENARIO_BLOCK_LOAD) iotScen.loadScenario("/scenario.json", ""); + iotScen.loadScenario("/scenario.txt"); // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 04527a3f..4ae13341 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -1,5 +1,3 @@ -#include - #pragma once #include "Global.h" #include "classes/IoTItem.h" @@ -7,6 +5,7 @@ #include "utils/FileUtils.h" #include "NTP.h" + bool isIotScenException; // признак исключения и попытки прекратить выполнение сценария заранее // Лексический анализатор возвращает токены [0-255], если это неизвестны, @@ -586,11 +585,9 @@ class BracketsExprAST : public ExprAST { // Lexer (Лексический анализатор) //===----------------------------------------------------------------------===// -char IoTScenario::getLastChar() { - if (strIterator == strFromFile.length()) return 0; - char tmpCh = strFromFile.charAt(strIterator); - strIterator++; - return tmpCh; +int IoTScenario::getLastChar() { + if (file) return file.read(); + else return EOF; } /// gettok - Возвращает следующий токен из стандартного потока ввода. @@ -600,9 +597,9 @@ int IoTScenario::gettok() { LastChar = getLastChar(); if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]* - IdentifierStr = LastChar; + IdentifierStr = (char)LastChar; while (isalnum((LastChar = getLastChar())) || LastChar == '_') { - IdentifierStr += LastChar; + IdentifierStr += (char)LastChar; } // Serial.printf("%s ", IdentifierStr.c_str()); @@ -616,7 +613,7 @@ int IoTScenario::gettok() { if (isdigit(LastChar)) { // Число: [0-9.]+ String NumStr; do { - NumStr += LastChar; + NumStr += (char)LastChar; LastChar = getLastChar(); } while (isdigit(LastChar) || LastChar == '.'); @@ -627,7 +624,7 @@ int IoTScenario::gettok() { if (LastChar == '#') { // Комментарий до конца строки do LastChar = getLastChar(); - while (LastChar != 0 && LastChar != '\n' && LastChar != '\r'); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); @@ -636,8 +633,8 @@ int IoTScenario::gettok() { if (LastChar == '"') { // "строка" IdentifierStr = ""; LastChar = getLastChar(); - while (LastChar != '"' && LastChar != 0) { - IdentifierStr += LastChar; + while (LastChar != '"' && LastChar != EOF) { + IdentifierStr += (char)LastChar; LastChar = getLastChar(); } LastChar = getLastChar(); @@ -646,8 +643,8 @@ int IoTScenario::gettok() { } // Проверка конца файла. - // if (LastChar == EOF) - // return tok_eof; + if (LastChar == EOF) + return tok_eof; if (LastChar == '=') { LastChar = getLastChar(); @@ -684,7 +681,7 @@ int IoTScenario::gettok() { } else return '>'; } - + // В противном случае просто возвращаем символ как значение ASCII int ThisChar = LastChar; LastChar = getLastChar(); @@ -919,78 +916,37 @@ ExprAST *IoTScenario::ParseExpression(String *IDNames) { return ParseBinOpRHS(0, LHS, IDNames); } -void IoTScenario::clearScenarioElements() { // удаляем все корневые элементы дерева AST - for (unsigned int i = 0; i < ScenarioElements.size(); i++) { - if (ScenarioElements[i]) delete ScenarioElements[i]; - } - ScenarioElements.clear(); + +void IoTScenario::loadScenario(String fileName) { // подготавливаем контекст для чтения и интерпретации файла + if (file) file.close(); + file = FileFS.open(fileName, "r"); } -void IoTScenario::loadScenario(String fileName, String eventIdName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST - if (!SCENARIO_BLOCK_LOAD) clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых. - LastChar = ' '; - - File myfile = seekFile(fileName); - if (myfile.available()) { - //strFromFile = new String(""); - - strFromFile = myfile.readString(); - //Serial.println(strFromF); - //jsonRead(strFromF, "scen", *strFromFile, true); - myfile.close(); - - strFromFile.replace("{\"scen\":\"", ""); - strFromFile.replace("\\n\"}", ""); - strFromFile.replace("\\n", "\n"); - strFromFile.replace("\\\"", "\""); - //Serial.println(strFromFile); - - if (strFromFile.length()) { - - while (strIterator < strFromFile.length()) { - // Serial.printf("-%c", LastChar); - getNextToken(); - switch (CurTok) { - // case tok_eof: break; - case tok_if: { - String IDNames = ""; // накопитель встречающихся идентификаторов в условии - ExprAST *tmpAST = ParseIfExpr(&IDNames); - if (!tmpAST) break; - - if (SCENARIO_BLOCK_LOAD) { - if (tmpAST->hasEventIdName(eventIdName)) { - tmpAST->exec(); - Serial.println("Exec from loadIF"); - } - delete tmpAST; - } else ScenarioElements.push_back(tmpAST); - break; - } - - default: - - break; - } - } - } - - //delete strFromFile; - strIterator = 0; - } else { +void IoTScenario::exec(String eventIdName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST + if (!file) { Error("Open file scenario error"); + return; + } + LastChar = 0; + CurTok = 0; + file.seek(0); + + while ((getNextToken()) != EOF) { + switch (CurTok) { + case tok_if: { + IDNames = ""; // сбрасываем накопитель встречающихся идентификаторов в условии + ExprAST *tmpAST = ParseIfExpr(&IDNames); + if (!tmpAST) break; + + if (tmpAST->hasEventIdName(eventIdName)) { + tmpAST->exec(); + } + delete tmpAST; + break;} + } } } -void IoTScenario::execScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы - // eventIdName - ID элемента для которого выполняем сценарий, т.е. игнорируем любые проверки, если нет такого ID в условиях - isIotScenException = false; - //Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); - for (unsigned int i = 0; i < ScenarioElements.size(); i++) { - if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); - // else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); - if (isIotScenException) return; - } -} IoTScenario::IoTScenario() { // Задаём стандартные бинарные операторы. @@ -1010,4 +966,6 @@ IoTScenario::IoTScenario() { BinopPrecedence['*'] = 28; // highest. } -IoTScenario::~IoTScenario() {} +IoTScenario::~IoTScenario() { + if (file) file.close(); +}