From 561245a5e53f8e1f5e0d105d4e83caa38a9d450b Mon Sep 17 00:00:00 2001 From: Ilya Belyakov Date: Thu, 16 Nov 2023 22:36:07 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B5=D0=BC=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8C=20Uart=20=D0=BD=D0=B0=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D0=B0=20IoTUart=20=D0=A4=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BE=D1=81=D1=82=D0=B0=D0=BB=D0=B8=D1=81=D1=8C=20?= =?UTF-8?q?=D1=82=D0=B5=20=D0=B6=D0=B5,=20=D0=BD=D0=BE=20=D1=83=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20=D1=8D=D0=BA=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D0=B0=D0=BC=D0=B8=20Dwin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/sensors/UART/Uart.cpp | 244 ++------------------------ src/modules/sensors/UART/modinfo.json | 2 +- 2 files changed, 18 insertions(+), 228 deletions(-) diff --git a/src/modules/sensors/UART/Uart.cpp b/src/modules/sensors/UART/Uart.cpp index 27bc898e..6fbf04e2 100644 --- a/src/modules/sensors/UART/Uart.cpp +++ b/src/modules/sensors/UART/Uart.cpp @@ -1,5 +1,6 @@ #include "Global.h" +#include "classes/IoTUart.h" #include "classes/IoTItem.h" #include @@ -11,37 +12,15 @@ HardwareSerial* myUART = nullptr; #endif -class IoTmUART : public IoTItem { +class IoTmUART : public IoTUart { 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; -#else - HardwareSerial* _myUART = nullptr; -#endif public: - IoTmUART(String parameters) : IoTItem(parameters) { - int _tx, _rx, _speed, _line; - jsonRead(parameters, "tx", _tx); - jsonRead(parameters, "rx", _rx); - jsonRead(parameters, "speed", _speed); - jsonRead(parameters, "line", _line); + IoTmUART(String parameters) : IoTUart(parameters) { jsonRead(parameters, "eventFormat", _eventFormat); - -#ifdef ESP8266 - myUART = _myUART = new SoftwareSerial(_rx, _tx); - _myUART->begin(_speed); -#endif -#ifdef ESP32 - myUART = _myUART = new HardwareSerial(_line); - _myUART->begin(_speed, SERIAL_8N1, _rx, _tx); -#endif } // проверяем формат и если событие, то регистрируем его @@ -72,47 +51,9 @@ class IoTmUART : public IoTItem { void uartHandle() { if (!_myUART) return; - if (_myUART->available()) { - if (_eventFormat == 3) { // третий режим, значит ожидаем бинарный пакет данных от dwin - _headerBuf[_headerIndex] = _myUART->read(); - - // ищем валидный заголовок пакета 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++; - + if (_eventFormat == 3) { // третий режим, значит ожидаем бинарный пакет данных от dwin оставлен для совместимости с предыдущей версией модуля + // используйте новый модуль для dwin DwinI } else { _inc = _myUART->read(); if (_inc == 0xFF) { @@ -148,7 +89,6 @@ class IoTmUART : public IoTItem { case 2: // формат событий для Nextion ID=Value0xFF0xFF0xFF printStr += eventItem->getID(); indexOf_ = printStr.indexOf("_"); - //Serial.println(printStr + " fff " + indexOf_); if (indexOf_ == -1) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol if (printStr.indexOf("_txt") > 0) { @@ -168,114 +108,25 @@ class IoTmUART : public IoTItem { uartPrintFFF(printStr); break; - - case 3: // формат событий для Dwin - printStr = eventItem->getID(); - indexOf_ = printStr.indexOf("_"); - uint8_t sizeOfVPPart = printStr.length() - indexOf_ - 1; - if (indexOf_ == -1 || !_myUART || sizeOfVPPart < 4 || indexOf_ == 0) return; // пропускаем событие, если нет признака _ или признак пустой - - char typeOfVP = sizeOfVPPart == 5 ? printStr.charAt(indexOf_ + 5) : 0; - String VP = printStr.substring(indexOf_ + 1, indexOf_ + 5); - - if (typeOfVP == 0) { // если не указан тип, то додумываем на основании типа данных источника - if (eventItem->value.isDecimal) - typeOfVP = 'i'; - else - typeOfVP = 's'; - } - - 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(); - } - - // подсчитываем количество символов отличающихся от ASCII, для понимания сколько символов состоит из дух байт - int u16counter = 0; - const char* valSptr = eventItem->value.valS.c_str(); - for (int i=0; i < eventItem->value.valS.length(); i++) { - if (valSptr[i] > 200) u16counter++; - } - - _myUART->write(0x5A); - _myUART->write(0xA5); - _myUART->write((eventItem->value.valS.length() - u16counter) * 2 + 5); // подсчитываем и отправляем размер итоговой строки + служебные байты - _myUART->write(0x82); // требуем запись в память - uartPrintHex(VP); // отправляем адрес в памяти VP - uartPrintStrInUTF16(eventItem->value.valS.c_str(), eventItem->value.valS.length()); // отправляем строку для записи - _myUART->write(0xFF); // терминируем строку, чтоб экран очистил все остальное в элементе своем - _myUART->write(0xFF); - - //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; } } - void uartPrintStrInUTF16(const char *strUTF8, int length) { - // очень жесткий но быстрый способ конвертирования UTF-8 в UTF-16, но с поддержкой только кириллицы и двух байт в UTF-8 - // не определяются исключения по формату UTF-8 - for (int i=0; i < length; i++) { - if (strUTF8[i] < 176) { // если байт соответствует коду ASCII, значит берем как есть, но расширяем до двух байт - _myUART->write(0x00); - _myUART->write(strUTF8[i]); - } else { // иначе понимаем, что имеем дело с двумя байтами (да UTF8 может иметь и больше, но это ограничение наше) - _myUART->write(0x04); // указываем номер диапазона символов кириллицы первым байтом на выходе - - if (strUTF8[i] == 208) { // если первый байт символа в первом диапазоне - if (strUTF8[i+1] == 129) _myUART->write(0x01); // исключение для символа 'ё' - else _myUART->write(strUTF8[i+1] - 128); // применяем смещение 128 и отправляем второй байт - } + IoTValue execute(String command, std::vector ¶m) { + if (command == "printFFF") { + if (param.size() == 2) { + String strToUart = ""; + strToUart = param[0].valS; - if (strUTF8[i] == 209) { // если первый байт символа во втором диапазоне - if (strUTF8[i+1] == 145) _myUART->write(0x51); // исключение для символа 'Ё' - else _myUART->write(strUTF8[i+1] - 64); // применяем смещение 64 и отправляем второй байт - } - - i++; // пропускаем второй байт входной строки + if (param[1].valD) + uartPrintFFF("\"" + strToUart + "\""); + else + uartPrintFFF(strToUart); } + } else { // не забываем, что переопределяем execute и нужно проверить что в базовом классе проверяется + return IoTUart::execute(command, param); } - } - virtual void loop() { - uartHandle(); + return {}; } void uartPrintFFF(const String& msg) { @@ -286,67 +137,6 @@ class IoTmUART : public IoTItem { _myUART->write(0xff); } } - - void uartPrintln(const String& msg) { - if (_myUART) { - _myUART->println(msg); - } - } - - void uartPrint(const String& msg) { - if (_myUART) { - _myUART->print(msg); - } - } - - void uartPrintHex(const String& msg) { - if (!_myUART) return; - - unsigned char Hi, Lo; - uint8_t byteTx; - const char* strPtr = msg.c_str(); - while ((Hi = *strPtr++) && (Lo = *strPtr++)) { - byteTx = (ChartoHex(Hi) << 4) | ChartoHex(Lo); - _myUART->write(byteTx); - } - } - - IoTValue execute(String command, std::vector ¶m) { - if (command == "println") { - if (param.size() == 1) { - //if (param[0].isDecimal) uartPrintln((String)param[0].valD); - //else uartPrintln(param[0].valS); - uartPrintln(param[0].valS); - } - } else if (command == "print") { - if (param.size() == 1) { - //if (param[0].isDecimal) uartPrint((String)param[0].valD); - //else uartPrint(param[0].valS); - uartPrintln(param[0].valS); - } - } else if (command == "printHex") { - if (param.size() == 1) { - uartPrintHex(param[0].valS); - } - } else if (command == "printFFF") { - if (param.size() == 2) { - String strToUart = ""; - // if (param[0].isDecimal) - // strToUart = param[0].valD; - // else - // strToUart = param[0].valS; - strToUart = param[0].valS; - - if (param[1].valD) - uartPrintFFF("\"" + strToUart + "\""); - else - uartPrintFFF(strToUart); - } - } - - return {}; - } - }; void* getAPI_UART(String subtype, String param) { diff --git a/src/modules/sensors/UART/modinfo.json b/src/modules/sensors/UART/modinfo.json index 6eaa0e1c..e17a3f66 100644 --- a/src/modules/sensors/UART/modinfo.json +++ b/src/modules/sensors/UART/modinfo.json @@ -37,7 +37,7 @@ "rx": "RX пин", "speed": "Скорость UART", "line": "Актуально только для ESP32: номер линии hardUART. =2 rx=16 tx=17", - "eventFormat": "Выбор формата обмена сообщениями с другими контроллерами. =0 - не указан формат, значит не следим за событиями, =1 - формат событий IoTM с использованием json, =2 - формат событий для Nextion отправка событий: ID.val=Value0xFF0xFF0xFF прием ордеров: ID=Value. Отправляться будут события тех элементов, которые имеют суффикс в ИД _val или _txt, которые влияют на передаваемый формат, =3 - формат событий для экранов Dwin. Отправляться будут события тех элементов, которые имеют суффикс в ИД с указанием адреса VP для записи значения, например ID_5000. Пока поддерживается только вывод целых чисел, значения кнопки и текст." + "eventFormat": "Выбор формата обмена сообщениями с другими контроллерами. =0 - не указан формат, значит не следим за событиями, =1 - формат событий IoTM с использованием json, =2 - формат событий для Nextion отправка событий: ID.val=Value0xFF0xFF0xFF прием ордеров: ID=Value. Отправляться будут события тех элементов, которые имеют суффикс в ИД _val или _txt, которые влияют на передаваемый формат." }, "retInfo": "Содержит полученное последнее по UART сообщение.", "funcInfo": [