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());