diff --git a/include/classes/IoTItem.h b/include/classes/IoTItem.h index 342bc02f..ff899a20 100644 --- a/include/classes/IoTItem.h +++ b/include/classes/IoTItem.h @@ -24,6 +24,7 @@ class IoTItem { String getSubtype(); String getID(); + bool isStrInID(const String& str); int getIntFromNet(); virtual String getValue(); long getInterval(); @@ -47,7 +48,7 @@ class IoTItem { virtual IoTGpio* getGpioDriver(); virtual IoTItem* getRtcDriver(); - virtual ulong getRtcUnixTime(); + virtual unsigned long getRtcUnixTime(); virtual void setValue(const IoTValue& Value, bool genEvent = true); virtual void setValue(const String& valStr, bool genEvent = true); @@ -91,6 +92,7 @@ class IoTItem { }; IoTItem* findIoTItem(const String& name); // поиск экземпляра элемента модуля по имени +IoTItem* findIoTItemByPartOfName(const String& partName); // поиск элемента модуля в существующей конфигурации по части имени String getItemValue(const String& name); // поиск плюс получение значения bool isItemExist(const String& name); // существует ли айтем //StaticJsonDocument* getLocalItemsAsJSON(); // сбор всех локальных значений Items diff --git a/platformio.ini b/platformio.ini index 42c25d4c..16c84fe2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -116,7 +116,6 @@ build_src_filter = lib_deps = ${common_env_data.lib_deps_external} ${env:esp32_4mb_fromitems.lib_deps} - plerup/EspSoftwareSerial@^7.0.0 build_flags = -Desp32_4mb="esp32_4mb" framework = arduino board = esp32dev @@ -264,7 +263,7 @@ lib_deps = https://github.com/tremaru/iarduino_RTC robtillaart/SHT2x@^0.1.1 WEMOS SHT3x@1.0.0 - plerup/EspSoftwareSerial@^7.0.0 + plerup/EspSoftwareSerial adafruit/Adafruit MCP23017 Arduino Library@^2.1.0 adafruit/Adafruit BusIO @ ^1.13.2 dfrobot/DFRobotDFPlayerMini @ ^1.0.5 @@ -313,7 +312,7 @@ lib_deps = https://github.com/tremaru/iarduino_RTC robtillaart/SHT2x@^0.1.1 WEMOS SHT3x@1.0.0 - plerup/espsoftwareserial + plerup/EspSoftwareSerial https://github.com/RoboticsBrno/ServoESP32 adafruit/Adafruit MCP23017 Arduino Library@^2.1.0 adafruit/Adafruit BusIO @ ^1.13.2 @@ -351,6 +350,5 @@ build_src_filter = + + + - + + diff --git a/src/EventsAndOrders.cpp b/src/EventsAndOrders.cpp index 2af00a66..20416471 100644 --- a/src/EventsAndOrders.cpp +++ b/src/EventsAndOrders.cpp @@ -51,10 +51,16 @@ void handleEvent() { if (eventBuf.length()) { String event = selectToMarker(eventBuf, ","); SerialPrint("i", F("EVENT"), event); + String enentIdName = selectToMarker(event, " "); + + // распространяем событие через хуки + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + (*it)->onRegEvent(findIoTItem(enentIdName)); + } //здесь нужно пропускать данное событие через условия сценариев //и если оно есть в условии сценария и совподает - iotScen.exec(selectToMarker(event, " ")); + iotScen.exec(enentIdName); eventBuf = deleteBeforeDelimiter(eventBuf, ","); } diff --git a/src/classes/IoTItem.cpp b/src/classes/IoTItem.cpp index 26fb41d1..73918f46 100644 --- a/src/classes/IoTItem.cpp +++ b/src/classes/IoTItem.cpp @@ -101,11 +101,6 @@ void IoTItem::regEvent(const String& value, const String& consoleInfo, bool erro if (genEvent) { generateEvent(_id, value); - // распространяем событие через хуки - for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { - (*it)->onRegEvent(this); - } - // отправка события другим устройствам в сети если не было ошибки if (_global && !error) { String json = "{}"; @@ -200,6 +195,10 @@ String IoTItem::getID() { return _id; }; +bool IoTItem::isStrInID(const String& str) { + return _id.indexOf(str) != -1; +} + void IoTItem::setInterval(long interval) { _interval = interval; } @@ -212,7 +211,7 @@ IoTItem* IoTItem::getRtcDriver() { return nullptr; } -ulong IoTItem::getRtcUnixTime() { +unsigned long IoTItem::getRtcUnixTime() { return 0; } @@ -245,6 +244,17 @@ IoTItem* findIoTItem(const String& name) { return nullptr; } + +// поиск элемента модуля в существующей конфигурации по части имени +IoTItem* findIoTItemByPartOfName(const String& partName) { + if (partName == "") return nullptr; + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + if ((*it)->isStrInID(partName)) return *it; + } + + return nullptr; +} + // поиск плюс получение значения String getItemValue(const String& name) { IoTItem* tmp = findIoTItem(name); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 9980fce0..b1c7b988 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -156,8 +156,8 @@ class BinaryExprAST : public ExprAST { IoTValue *lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда if (lhs == nullptr) return nullptr; - // все бинарные операции кроме +, - и == обязаны работать с числами - if (Op != '+' && Op != '-' && Op != tok_equal) { + // все бинарные операции кроме +, -, != и == обязаны работать с числами + if (Op != '+' && Op != '-' && Op != tok_equal && Op != tok_notequal) { // поэтому преобразовываем строки в булевые интерпретации if (!lhs->isDecimal) lhs->valD = lhs->valS != ""; // пустая строка = false if (!rhs->isDecimal) rhs->valD = rhs->valS != ""; // пустая строка = false @@ -175,9 +175,6 @@ class BinaryExprAST : public ExprAST { case tok_greateq: val.valD = lhs->valD >= rhs->valD; break; - case tok_notequal: - val.valD = lhs->valD != rhs->valD; - break; case '*': val.valD = lhs->valD * rhs->valD; @@ -199,7 +196,7 @@ class BinaryExprAST : public ExprAST { default: break; } - } else { // иначе имеем дело с операциями + или - или ==, которые могут работать с разными типами данных + } else { // иначе имеем дело с операциями + или - или == или !=, которые могут работать с разными типами данных if (lhs->isDecimal && lhs->valS == "") lhs->valS = (String)lhs->valD; // небольшой костыль пока не переделаем работу со значениями, планируется добавить long, работу со временем, перенести округление и модификаторы в IoTValue if (rhs->isDecimal && rhs->valS == "") rhs->valS = (String)rhs->valD; // пока для сохранения округления в IoTItem применяется хитрость с сохранением внешнего вида числа в строку valS, // но некоторые модули и системные не делают этого, поэтому отлавливаем эту ситуацию тут и учитываем. @@ -211,6 +208,13 @@ class BinaryExprAST : public ExprAST { val.valD = compStr(lhs->valS, rhs->valS); break; + case tok_notequal: + if (lhs->isDecimal && rhs->isDecimal) + val.valD = lhs->valD != rhs->valD; + else + val.valD = !compStr(lhs->valS, rhs->valS); + break; + case '+': if (lhs->isDecimal && rhs->isDecimal) val.valD = lhs->valD + rhs->valD; diff --git a/src/modules/exec/HttpGet/modinfo.json b/src/modules/exec/HttpGet/modinfo.json index c48638a5..b954636a 100644 --- a/src/modules/exec/HttpGet/modinfo.json +++ b/src/modules/exec/HttpGet/modinfo.json @@ -34,14 +34,14 @@ "name": "get", "descr": "Отправить http запрос методом GET.", "params": [ - "http.get('URL')" + "URL" ] }, { "name": "post", "descr": "Отправить http запрос методом POST.", "params": [ - "http.post('URL','message')" + "URL","message" ] } ] diff --git a/src/modules/sensors/Pzem004t/Pzem004t.cpp b/src/modules/sensors/Pzem004t/Pzem004t.cpp index 8aa8b1c2..1cfccaa8 100644 --- a/src/modules/sensors/Pzem004t/Pzem004t.cpp +++ b/src/modules/sensors/Pzem004t/Pzem004t.cpp @@ -28,7 +28,7 @@ class Pzem004v : public IoTItem { regEvent(value.valD, "Pzem V"); } else { regEvent(NAN, "Pzem V"); - SerialPrint("E", "Pzem", "V error"); + SerialPrint("E", "Pzem", "V error", _id); } } } @@ -57,7 +57,7 @@ class Pzem004a : public IoTItem { regEvent(value.valD, "Pzem A"); } else { regEvent(NAN, "Pzem A"); - SerialPrint("E", "Pzem", "A error"); + SerialPrint("E", "Pzem", "A error", _id); } } } @@ -86,7 +86,7 @@ class Pzem004w : public IoTItem { regEvent(value.valD, "Pzem W"); } else { regEvent(NAN, "Pzem W"); - SerialPrint("E", "Pzem", "W error"); + SerialPrint("E", "Pzem", "W error", _id); } } } @@ -115,7 +115,7 @@ class Pzem004wh : public IoTItem { regEvent(value.valD, "Pzem Wh"); } else { regEvent(NAN, "Pzem Wh"); - SerialPrint("E", "Pzem", "Wh error"); + SerialPrint("E", "Pzem", "Wh error", _id); } } } @@ -144,7 +144,7 @@ class Pzem004hz : public IoTItem { regEvent(value.valD, "Pzem Hz"); } else { regEvent(NAN, "Pzem Hz"); - SerialPrint("E", "Pzem", "Hz error"); + SerialPrint("E", "Pzem", "Hz error", _id); } } } @@ -173,7 +173,7 @@ class Pzem004pf : public IoTItem { regEvent(value.valD, "Pzem Pf"); } else { regEvent(NAN, "Pzem Pf"); - SerialPrint("E", "Pzem", "Pf error"); + SerialPrint("E", "Pzem", "Pf error", _id); } } } diff --git a/src/modules/sensors/UART/Uart.cpp b/src/modules/sensors/UART/Uart.cpp index 5428eecd..27bc898e 100644 --- a/src/modules/sensors/UART/Uart.cpp +++ b/src/modules/sensors/UART/Uart.cpp @@ -11,9 +11,13 @@ HardwareSerial* myUART = nullptr; #endif -class UART : public IoTItem { +class IoTmUART : public IoTItem { private: int _eventFormat = 0; // 0 - нет приема, 1 - json IoTM, 2 - Nextion + char _inc; + String _inStr = ""; // буфер приема строк в режимах 0, 1, 2 + uint8_t _headerBuf[260]; // буфер для приема пакета dwin + int _headerIndex = 0; // счетчик принятых байт пакета #ifdef ESP8266 SoftwareSerial* _myUART = nullptr; @@ -22,7 +26,7 @@ class UART : public IoTItem { #endif public: - UART(String parameters) : IoTItem(parameters) { + IoTmUART(String parameters) : IoTItem(parameters) { int _tx, _rx, _speed, _line; jsonRead(parameters, "tx", _tx); jsonRead(parameters, "rx", _rx); @@ -70,23 +74,61 @@ class UART : public IoTItem { if (!_myUART) return; if (_myUART->available()) { - static String inStr = ""; - char inc; - - inc = _myUART->read(); - if (inc == 0xFF) { - inc = _myUART->read(); - inc = _myUART->read(); - inStr = ""; - return; - } + if (_eventFormat == 3) { // третий режим, значит ожидаем бинарный пакет данных от dwin + _headerBuf[_headerIndex] = _myUART->read(); - if (inc == '\r') return; - - if (inc == '\n') { - analyzeString(inStr); - inStr = ""; - } else inStr += inc; + // ищем валидный заголовок пакета dwin, проверяя каждый следующий байт + if (_headerIndex == 0 && _headerBuf[_headerIndex] != 0x5A || + _headerIndex == 1 && _headerBuf[_headerIndex] != 0xA5 || + _headerIndex == 2 && _headerBuf[_headerIndex] == 0 || + _headerIndex == 3 && _headerBuf[_headerIndex] == 0x82 ) { + _headerIndex = 0; + return; + } + + if (_headerIndex == _headerBuf[2] + 2) { // получили все данные из пакета + // Serial.print("ffffffff"); + // for (int i=0; i<=_headerIndex; i++) + // Serial.printf("%#x ", _headerBuf[i]); + // Serial.println("!!!"); + + String valStr, id = "_"; + if (_headerIndex == 8) { // предполагаем, что получили int16 + valStr = (String)((_headerBuf[7] << 8) | _headerBuf[8]); + } + + char buf[5]; + hex2string(_headerBuf + 4, 2, buf); + id += (String)buf; + + IoTItem* item = findIoTItemByPartOfName(id); + if (item) { + //Serial.printf("received data: %s for VP: %s for ID: %s\n", valStr, buf, item->getID()); + generateOrder(item->getID(), valStr); + } + + _headerIndex = 0; + return; + } + + _headerIndex++; + + } else { + _inc = _myUART->read(); + if (_inc == 0xFF) { + _inc = _myUART->read(); + _inc = _myUART->read(); + _inStr = ""; + return; + } + + if (_inc == '\r') return; + + if (_inc == '\n') { + analyzeString(_inStr); + _inStr = ""; + } else _inStr += _inc; + } } } @@ -128,51 +170,81 @@ class UART : public IoTItem { break; case 3: // формат событий для Dwin - //for (int i=0; i<2; i++) { printStr = eventItem->getID(); indexOf_ = printStr.indexOf("_"); - if (indexOf_ == -1 || !_myUART) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol + uint8_t sizeOfVPPart = printStr.length() - indexOf_ - 1; + if (indexOf_ == -1 || !_myUART || sizeOfVPPart < 4 || indexOf_ == 0) return; // пропускаем событие, если нет признака _ или признак пустой - String VP = selectToMarkerLast(printStr, "_"); + char typeOfVP = sizeOfVPPart == 5 ? printStr.charAt(indexOf_ + 5) : 0; + String VP = printStr.substring(indexOf_ + 1, indexOf_ + 5); - _myUART->write(0x5A); - _myUART->write(0xA5); + if (typeOfVP == 0) { // если не указан тип, то додумываем на основании типа данных источника + if (eventItem->value.isDecimal) + typeOfVP = 'i'; + else + typeOfVP = 's'; + } - if (eventItem->value.isDecimal) { // пока отправляем только целые числа + if (typeOfVP == 'i') { + _myUART->write(0x5A); + _myUART->write(0xA5); _myUART->write(0x05); // размер данных отправляемых с учетом целых чисел int _myUART->write(0x82); // требуем запись в память uartPrintHex(VP); // отправляем адрес в памяти VP + + if (!eventItem->value.isDecimal) { + eventItem->value.valD = atoi(eventItem->value.valS.c_str()); + } + + _myUART->write(highByte((int)eventItem->value.valD)); + _myUART->write(lowByte((int)eventItem->value.valD)); + } + + if (typeOfVP == 's') { + if (eventItem->value.isDecimal) { + eventItem->value.valS = eventItem->getValue(); + } - byte raw[2]; - (int&)raw = eventItem->value.valD; - _myUART->write(raw[1]); - _myUART->write(raw[0]); - } else { // подсчитываем количество символов отличающихся от ASCII, для понимания сколько символов состоит из дух байт int u16counter = 0; const char* valSptr = eventItem->value.valS.c_str(); - //Serial.print("iiiii "); for (int i=0; i < eventItem->value.valS.length(); i++) { if (valSptr[i] > 200) u16counter++; - //Serial.printf("%d ", valSptr[i]); } - //Serial.println(); + _myUART->write(0x5A); + _myUART->write(0xA5); _myUART->write((eventItem->value.valS.length() - u16counter) * 2 + 5); // подсчитываем и отправляем размер итоговой строки + служебные байты _myUART->write(0x82); // требуем запись в память uartPrintHex(VP); // отправляем адрес в памяти VP - Serial.println("ffffff " + VP); - //_myUART->write(0x53); - //_myUART->write(0x00); uartPrintStrInUTF16(eventItem->value.valS.c_str(), eventItem->value.valS.length()); // отправляем строку для записи _myUART->write(0xFF); // терминируем строку, чтоб экран очистил все остальное в элементе своем _myUART->write(0xFF); - //uint8_t Data[8] = {0x00, 0x31, 0x00, 0x44, 0x04, 0x10, 0x00, 0x00}; - //uartPrintArray(Data, 6); //Serial.printf("fffffffff %#x %#x %#x %#x \n", Data[0], Data[1], Data[2], Data[3]); } - //} + + if (typeOfVP == 'f') { + _myUART->write(0x5A); + _myUART->write(0xA5); + _myUART->write(0x07); // размер данных отправляемых с учетом дробных чисел dword + _myUART->write(0x82); // требуем запись в память + uartPrintHex(VP); // отправляем адрес в памяти VP + + byte hex[4] = {0}; + if (!eventItem->value.isDecimal) { + eventItem->value.valD = atof(eventItem->value.valS.c_str()); + } + + byte* f_byte = reinterpret_cast(&(eventItem->value.valD)); + memcpy(hex, f_byte, 4); + + _myUART->write(hex[3]); + _myUART->write(hex[2]); + _myUART->write(hex[1]); + _myUART->write(hex[0]); + } + break; } } @@ -202,10 +274,6 @@ class UART : public IoTItem { } } - void uartPrintArray(uint8_t *_Data, uint8_t _Size) { - for (size_t i = 0; i < _Size; i++) _myUART->write(_Data[i]); - } - virtual void loop() { uartHandle(); } @@ -283,7 +351,7 @@ class UART : public IoTItem { void* getAPI_UART(String subtype, String param) { if (subtype == F("UART")) { - return new UART(param); + return new IoTmUART(param); } else { return nullptr; } diff --git a/src/modules/sensors/UART/modinfo.json b/src/modules/sensors/UART/modinfo.json index b32dbde0..041f2ca1 100644 --- a/src/modules/sensors/UART/modinfo.json +++ b/src/modules/sensors/UART/modinfo.json @@ -66,10 +66,10 @@ "defActive": true, "usedLibs": { "esp32_4mb": [ - "plerup/EspSoftwareSerial@^7.0.0" + "plerup/EspSoftwareSerial" ], "esp8266_4mb": [ - "plerup/EspSoftwareSerial@^7.0.0" + "plerup/EspSoftwareSerial" ] } } \ No newline at end of file