2022-09-26 21:56:54 +02:00
|
|
|
|
|
|
|
|
|
|
#include "Global.h"
|
|
|
|
|
|
#include "classes/IoTItem.h"
|
|
|
|
|
|
#include <Arduino.h>
|
2022-09-27 00:52:53 +02:00
|
|
|
|
|
2022-09-27 01:24:22 +02:00
|
|
|
|
#include "modules/sensors/UART/Uart.h"
|
2022-09-26 21:56:54 +02:00
|
|
|
|
|
|
|
|
|
|
#ifdef ESP8266
|
2022-11-04 17:01:12 +03:00
|
|
|
|
SoftwareSerial* myUART = nullptr;
|
2022-09-26 21:56:54 +02:00
|
|
|
|
#else
|
2022-11-04 17:01:12 +03:00
|
|
|
|
HardwareSerial* myUART = nullptr;
|
2022-09-26 21:56:54 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
|
2022-09-27 01:24:22 +02:00
|
|
|
|
class UART : public IoTItem {
|
2022-09-26 21:56:54 +02:00
|
|
|
|
private:
|
2022-11-04 17:01:12 +03:00
|
|
|
|
int _eventFormat = 0; // 0 - нет приема, 1 - json IoTM, 2 - Nextion
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef ESP8266
|
|
|
|
|
|
SoftwareSerial* _myUART = nullptr;
|
|
|
|
|
|
#else
|
|
|
|
|
|
HardwareSerial* _myUART = nullptr;
|
|
|
|
|
|
#endif
|
2022-09-26 21:56:54 +02:00
|
|
|
|
|
|
|
|
|
|
public:
|
2022-09-27 01:24:22 +02:00
|
|
|
|
UART(String parameters) : IoTItem(parameters) {
|
2022-11-10 00:39:18 +05:00
|
|
|
|
int _tx, _rx, _speed, _line;
|
2022-11-04 17:01:12 +03:00
|
|
|
|
jsonRead(parameters, "tx", _tx);
|
|
|
|
|
|
jsonRead(parameters, "rx", _rx);
|
|
|
|
|
|
jsonRead(parameters, "speed", _speed);
|
2022-11-10 00:39:18 +05:00
|
|
|
|
jsonRead(parameters, "line", _line);
|
2022-11-04 17:01:12 +03:00
|
|
|
|
jsonRead(parameters, "eventFormat", _eventFormat);
|
2022-09-26 21:56:54 +02:00
|
|
|
|
|
|
|
|
|
|
#ifdef ESP8266
|
2022-11-10 00:39:18 +05:00
|
|
|
|
myUART = _myUART = new SoftwareSerial(_rx, _tx);
|
2022-11-04 17:01:12 +03:00
|
|
|
|
_myUART->begin(_speed);
|
2022-09-26 21:56:54 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef ESP32
|
2022-11-10 00:39:18 +05:00
|
|
|
|
myUART = _myUART = new HardwareSerial(_line);
|
2022-11-06 13:07:52 +03:00
|
|
|
|
_myUART->begin(_speed, SERIAL_8N1, _rx, _tx);
|
2022-09-26 21:56:54 +02:00
|
|
|
|
#endif
|
2022-11-04 17:01:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// проверяем формат и если событие, то регистрируем его
|
|
|
|
|
|
void analyzeString(const String& msg) {
|
|
|
|
|
|
switch (_eventFormat) {
|
|
|
|
|
|
case 0: // не указан формат, значит все полученные данные воспринимаем как общее значение из UART
|
|
|
|
|
|
setValue(msg);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 1: // формат событий IoTM с использованием json, значит создаем временную копию
|
|
|
|
|
|
analyzeMsgFromNet(msg);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 2: // формат команд от Nextion ID=Value
|
2022-11-07 12:03:46 +03:00
|
|
|
|
if (msg.indexOf("=") == -1) { // если входящее сообщение не по формату, то работаем как в режиме 0
|
|
|
|
|
|
setValue(msg);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2022-11-04 17:01:12 +03:00
|
|
|
|
String id = selectToMarker(msg, "=");
|
|
|
|
|
|
String valStr = selectToMarkerLast(msg, "=");
|
|
|
|
|
|
valStr.replace("\"", "");
|
2022-11-08 19:59:17 +03:00
|
|
|
|
id.replace(".val", "_val");
|
|
|
|
|
|
id.replace(".txt", "_txt");
|
2022-11-04 17:15:59 +03:00
|
|
|
|
generateOrder(id, valStr);
|
2022-11-04 17:01:12 +03:00
|
|
|
|
break;
|
2022-09-26 21:56:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void uartHandle() {
|
2022-11-04 17:01:12 +03:00
|
|
|
|
if (!_myUART) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (_myUART->available()) {
|
|
|
|
|
|
static String inStr = "";
|
|
|
|
|
|
char inc;
|
2022-11-04 18:58:13 +03:00
|
|
|
|
|
2022-11-04 17:01:12 +03:00
|
|
|
|
inc = _myUART->read();
|
2022-11-04 18:58:13 +03:00
|
|
|
|
if (inc == 0xFF) {
|
|
|
|
|
|
inc = _myUART->read();
|
|
|
|
|
|
inc = _myUART->read();
|
|
|
|
|
|
inStr = "";
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (inc == '\r') return;
|
|
|
|
|
|
|
2022-11-04 17:01:12 +03:00
|
|
|
|
if (inc == '\n') {
|
|
|
|
|
|
analyzeString(inStr);
|
|
|
|
|
|
inStr = "";
|
2022-11-04 18:58:13 +03:00
|
|
|
|
} else inStr += inc;
|
2022-09-26 21:56:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-04 17:01:12 +03:00
|
|
|
|
void onRegEvent(IoTItem* eventItem) {
|
2022-11-07 17:29:45 +03:00
|
|
|
|
if (!_myUART || !eventItem) return;
|
2023-01-30 21:47:05 +03:00
|
|
|
|
int indexOf_;
|
2022-11-04 17:01:12 +03:00
|
|
|
|
String printStr = "";
|
|
|
|
|
|
switch (_eventFormat) {
|
|
|
|
|
|
case 0: return; // не указан формат, значит не следим за событиями
|
|
|
|
|
|
case 1: // формат событий IoTM с использованием json
|
2022-11-07 17:29:45 +03:00
|
|
|
|
if (eventItem->isGlobal()) {
|
|
|
|
|
|
eventItem->getNetEvent(printStr);
|
|
|
|
|
|
_myUART->println(printStr);
|
|
|
|
|
|
}
|
2022-11-04 17:01:12 +03:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 2: // формат событий для Nextion ID=Value0xFF0xFF0xFF
|
|
|
|
|
|
printStr += eventItem->getID();
|
2023-01-30 21:47:05 +03:00
|
|
|
|
indexOf_ = printStr.indexOf("_");
|
2022-11-15 20:01:59 +03:00
|
|
|
|
//Serial.println(printStr + " fff " + indexOf_);
|
2022-11-14 19:28:14 +03:00
|
|
|
|
if (indexOf_ == -1) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol
|
2022-11-13 20:45:10 +05:00
|
|
|
|
|
|
|
|
|
|
if (printStr.indexOf("_txt") > 0) {
|
|
|
|
|
|
printStr.replace("_txt", ".txt=\"");
|
2022-11-07 17:29:45 +03:00
|
|
|
|
printStr += eventItem->getValue();
|
2022-11-04 17:01:12 +03:00
|
|
|
|
printStr += "\"";
|
2022-11-14 19:28:14 +03:00
|
|
|
|
} else if (printStr.indexOf("_val") > 0) {
|
2022-11-15 20:01:59 +03:00
|
|
|
|
printStr += eventItem->getValue();
|
2022-11-14 19:28:14 +03:00
|
|
|
|
printStr.replace(".", "");
|
|
|
|
|
|
printStr.replace("_val", ".val=");
|
2022-11-13 20:45:10 +05:00
|
|
|
|
} else {
|
2022-11-15 20:01:59 +03:00
|
|
|
|
if (indexOf_ == printStr.length()-1) printStr.replace("_", "");
|
2022-11-14 19:28:14 +03:00
|
|
|
|
else printStr.replace("_", ".");
|
2022-11-13 20:45:10 +05:00
|
|
|
|
printStr += "=";
|
2022-11-07 17:29:45 +03:00
|
|
|
|
printStr += eventItem->getValue();
|
2022-11-13 20:45:10 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-07 17:29:45 +03:00
|
|
|
|
uartPrintFFF(printStr);
|
2022-11-04 17:01:12 +03:00
|
|
|
|
break;
|
2023-01-30 21:47:05 +03:00
|
|
|
|
|
|
|
|
|
|
case 3: // формат событий для Dwin
|
|
|
|
|
|
//for (int i=0; i<2; i++) {
|
|
|
|
|
|
printStr = eventItem->getID();
|
|
|
|
|
|
indexOf_ = printStr.indexOf("_");
|
|
|
|
|
|
if (indexOf_ == -1 || !_myUART) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol
|
|
|
|
|
|
|
|
|
|
|
|
String VP = selectToMarkerLast(printStr, "_");
|
|
|
|
|
|
|
|
|
|
|
|
_myUART->write(0x5A);
|
|
|
|
|
|
_myUART->write(0xA5);
|
|
|
|
|
|
|
|
|
|
|
|
if (eventItem->value.isDecimal) { // пока отправляем только целые числа
|
|
|
|
|
|
_myUART->write(0x05); // размер данных отправляемых с учетом целых чисел int
|
|
|
|
|
|
_myUART->write(0x82); // требуем запись в память
|
|
|
|
|
|
uartPrintHex(VP); // отправляем адрес в памяти VP
|
|
|
|
|
|
|
|
|
|
|
|
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((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]);
|
|
|
|
|
|
}
|
|
|
|
|
|
//}
|
|
|
|
|
|
break;
|
2022-11-04 17:01:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-30 21:47:05 +03:00
|
|
|
|
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 и отправляем второй байт
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strUTF8[i] == 209) { // если первый байт символа во втором диапазоне
|
|
|
|
|
|
if (strUTF8[i+1] == 145) _myUART->write(0x51); // исключение для символа 'Ё'
|
|
|
|
|
|
else _myUART->write(strUTF8[i+1] - 64); // применяем смещение 64 и отправляем второй байт
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i++; // пропускаем второй байт входной строки
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void uartPrintArray(uint8_t *_Data, uint8_t _Size) {
|
|
|
|
|
|
for (size_t i = 0; i < _Size; i++) _myUART->write(_Data[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-04 17:01:12 +03:00
|
|
|
|
virtual void loop() {
|
|
|
|
|
|
uartHandle();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-07 17:29:45 +03:00
|
|
|
|
void uartPrintFFF(const String& msg) {
|
|
|
|
|
|
if (_myUART) {
|
|
|
|
|
|
_myUART->print(msg);
|
|
|
|
|
|
_myUART->write(0xff);
|
|
|
|
|
|
_myUART->write(0xff);
|
|
|
|
|
|
_myUART->write(0xff);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void uartPrintln(const String& msg) {
|
2022-11-04 17:01:12 +03:00
|
|
|
|
if (_myUART) {
|
|
|
|
|
|
_myUART->println(msg);
|
|
|
|
|
|
}
|
2022-09-26 21:56:54 +02:00
|
|
|
|
}
|
2022-09-27 01:07:50 +02:00
|
|
|
|
|
2022-11-07 17:29:45 +03:00
|
|
|
|
void uartPrint(const String& msg) {
|
|
|
|
|
|
if (_myUART) {
|
|
|
|
|
|
_myUART->print(msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-04 17:01:12 +03:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2022-09-27 01:07:50 +02:00
|
|
|
|
}
|
2022-11-04 17:01:12 +03:00
|
|
|
|
|
|
|
|
|
|
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
2022-11-07 17:29:45 +03:00
|
|
|
|
if (command == "println") {
|
2022-11-04 17:01:12 +03:00
|
|
|
|
if (param.size() == 1) {
|
2022-12-02 13:56:31 +03:00
|
|
|
|
//if (param[0].isDecimal) uartPrintln((String)param[0].valD);
|
|
|
|
|
|
//else uartPrintln(param[0].valS);
|
|
|
|
|
|
uartPrintln(param[0].valS);
|
2022-11-07 17:29:45 +03:00
|
|
|
|
}
|
|
|
|
|
|
} else if (command == "print") {
|
|
|
|
|
|
if (param.size() == 1) {
|
2022-12-02 13:56:31 +03:00
|
|
|
|
//if (param[0].isDecimal) uartPrint((String)param[0].valD);
|
|
|
|
|
|
//else uartPrint(param[0].valS);
|
|
|
|
|
|
uartPrintln(param[0].valS);
|
2022-11-04 17:01:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
} else if (command == "printHex") {
|
|
|
|
|
|
if (param.size() == 1) {
|
|
|
|
|
|
uartPrintHex(param[0].valS);
|
|
|
|
|
|
}
|
2022-11-07 17:29:45 +03:00
|
|
|
|
} else if (command == "printFFF") {
|
|
|
|
|
|
if (param.size() == 2) {
|
|
|
|
|
|
String strToUart = "";
|
2022-12-02 13:56:31 +03:00
|
|
|
|
// if (param[0].isDecimal)
|
|
|
|
|
|
// strToUart = param[0].valD;
|
|
|
|
|
|
// else
|
|
|
|
|
|
// strToUart = param[0].valS;
|
|
|
|
|
|
strToUart = param[0].valS;
|
2022-11-07 17:29:45 +03:00
|
|
|
|
|
|
|
|
|
|
if (param[1].valD)
|
|
|
|
|
|
uartPrintFFF("\"" + strToUart + "\"");
|
|
|
|
|
|
else
|
|
|
|
|
|
uartPrintFFF(strToUart);
|
|
|
|
|
|
}
|
2022-11-04 17:01:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-26 21:56:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2022-09-27 01:24:22 +02:00
|
|
|
|
void* getAPI_UART(String subtype, String param) {
|
|
|
|
|
|
if (subtype == F("UART")) {
|
|
|
|
|
|
return new UART(param);
|
2022-09-26 21:56:54 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|