mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-05-26 04:39:22 +03:00
Merge pull request #262 from biveraxe/ver4dev
Исправление ошибки контроля сетевых элементов
This commit is contained in:
@@ -35,7 +35,7 @@ extern FS* filesystem;
|
||||
extern bool fileSystemInit();
|
||||
extern void globalVarsSync();
|
||||
|
||||
extern String getParamsJson();
|
||||
//extern String getParamsJson();
|
||||
|
||||
extern void syncSettingsFlashJson();
|
||||
extern void syncValuesFlashJson();
|
||||
|
||||
@@ -73,8 +73,8 @@ class IoTItem {
|
||||
String _id = "errorId"; // если будет попытка создания Item без указания id, то элемент оставит это значение
|
||||
long _interval = 0;
|
||||
int _intFromNet = -2; // количество секунд доверия, пришедших из сети вместе с данными для текущего ИД
|
||||
// -2 - данные не приходили, скорее всего, элемент локальный, доверие есть
|
||||
// -1 - данные приходили и обратный отсчет дошел до нуля, значит доверия нет
|
||||
// -2 - данные не приходили, скорее всего, элемент локальный, доверие есть, в случае прихода сетевого значения с int=0, будет выключен механизм проверки доверия
|
||||
// -1 - данные приходили и обратный отсчет дошел до нуля, значит доверия нет и элемент будет удален при следующем такте loop
|
||||
|
||||
float _multiply; // умножаем на значение
|
||||
float _plus; // увеличиваем на значение
|
||||
@@ -90,7 +90,7 @@ class IoTItem {
|
||||
IoTItem* findIoTItem(const String& name); // поиск экземпляра элемента модуля по имени
|
||||
String getItemValue(const String& name); // поиск плюс получение значения
|
||||
bool isItemExist(const String& name); // существует ли айтем
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE>* getLocalItemsAsJSON(); // сбор всех локальных значений Items
|
||||
//StaticJsonDocument<JSON_BUFFER_SIZE>* getLocalItemsAsJSON(); // сбор всех локальных значений Items
|
||||
|
||||
IoTItem* createItemFromNet(const String& itemId, const String& value, int interval);
|
||||
IoTItem* createItemFromNet(const String& msgFromNet);
|
||||
|
||||
@@ -27,12 +27,12 @@ void globalVarsSync() {
|
||||
}
|
||||
|
||||
//к удалению. не используется
|
||||
String getParamsJson() {
|
||||
String json;
|
||||
serializeJson(*getLocalItemsAsJSON(), json);
|
||||
jsonWriteStr_(json, "params", "");
|
||||
return json;
|
||||
}
|
||||
// String getParamsJson() {
|
||||
// String json;
|
||||
// serializeJson(*getLocalItemsAsJSON(), json);
|
||||
// jsonWriteStr_(json, "params", "");
|
||||
// return json;
|
||||
// }
|
||||
|
||||
void syncSettingsFlashJson() {
|
||||
writeFile(F("settings.json"), settingsFlashJson);
|
||||
|
||||
@@ -91,7 +91,7 @@ void setup() {
|
||||
iotScen.loadScenario("/scenario.txt");
|
||||
|
||||
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
|
||||
createItemFromNet("onStart", "1", -4);
|
||||
createItemFromNet("onStart", "1", 1);
|
||||
|
||||
stInit();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ void periodicTasksInit() {
|
||||
// heap
|
||||
String heap = prettyBytes(ESP.getFreeHeap());
|
||||
SerialPrint(F("i"), F("HEAP"), heap);
|
||||
SerialPrint(F("i"), F("IoTItems"), (String)IoTItems.size());
|
||||
printGlobalVarSize();
|
||||
jsonWriteStr_(errorsHeapJson, F("heap"), heap);
|
||||
// rssi
|
||||
|
||||
@@ -119,7 +119,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
configure("/config.json");
|
||||
iotScen.loadScenario("/scenario.txt");
|
||||
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
|
||||
createItemFromNet("onStart", "1", -4);
|
||||
createItemFromNet("onStart", "1", 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------//
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
IoTItem::IoTItem(const String& parameters) {
|
||||
jsonRead(parameters, F("int"), _interval, false);
|
||||
if (_interval <= 0) enableDoByInt = false;
|
||||
_interval = _interval * 1000;
|
||||
if (_interval == 0) enableDoByInt = false; // выключаем использование периодического выполнения в модуле
|
||||
if (_interval > 0) _interval = _interval * 1000; // если int положителен, то считаем, что получены секунды
|
||||
if (_interval < 0) _interval = _interval * -1; // если int отрицательный, то миллисекунды
|
||||
jsonRead(parameters, F("subtype"), _subtype, false);
|
||||
jsonRead(parameters, F("id"), _id);
|
||||
if (!jsonRead(parameters, F("multiply"), _multiply, false)) _multiply = 1;
|
||||
@@ -170,7 +171,7 @@ void IoTItem::setIntFromNet(int interval) {
|
||||
void IoTItem::checkIntFromNet() {
|
||||
// проверяем элемент на доверие данным.
|
||||
if (_intFromNet >= 0) {
|
||||
// если время жизни истекло, то удаляем элемент
|
||||
// если время жизни истекло, то удаляем элемент чуть позже на следующем такте loop
|
||||
// если это было уведомление не об ошибке или начале работы, то сообщаем, что сетевое событие давно не приходило
|
||||
if (_intFromNet == 0 && _id.indexOf("onError") == -1 && _id.indexOf("onStart") == -1) {
|
||||
SerialPrint("E", _id, "The new data did not come from the network. The level of trust is low.", _id);
|
||||
@@ -270,6 +271,9 @@ IoTItem* createItemFromNet(const String& itemId, const String& value, int interv
|
||||
// создаем временную копию элемента из сети на основе события
|
||||
IoTItem* createItemFromNet(const String& msgFromNet) {
|
||||
IoTItem* tmpp = new IoTItem(msgFromNet);
|
||||
|
||||
//Serial.println("vvvvvvvvvvv " + msgFromNet + " " + (String)tmpp->getInterval());
|
||||
|
||||
if (tmpp->getInterval()) tmpp->setIntFromNet(tmpp->getInterval() / 1000 + 5);
|
||||
tmpp->iAmLocal = false;
|
||||
IoTItems.push_back(tmpp);
|
||||
@@ -278,7 +282,7 @@ IoTItem* createItemFromNet(const String& msgFromNet) {
|
||||
}
|
||||
|
||||
void analyzeMsgFromNet(const String& msg, String altId) {
|
||||
if (!jsonRead(msg, F("id"), altId, altId == "") && altId == "") return; // ничего не предпринимаем, если ошибка и altId = "", вообще данная конструкция нужна для совместимости с форматом данных 3 версией
|
||||
if (!jsonRead(msg, F("id"), altId, altId == "")) return; // ничего не предпринимаем, если ошибка и altId = "", вообще данная конструкция нужна для совместимости с форматом данных 3 версией
|
||||
IoTItem* itemExist = findIoTItem(altId);
|
||||
if (itemExist) {
|
||||
String valAsStr = msg;
|
||||
@@ -293,16 +297,17 @@ void analyzeMsgFromNet(const String& msg, String altId) {
|
||||
} else {
|
||||
// временно зафиксируем данные в базе, если локально элемент отсутствует
|
||||
createItemFromNet(msg);
|
||||
//Serial.println("ffffffffff " + msg + " altId=" + altId);
|
||||
}
|
||||
}
|
||||
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE> docForExport;
|
||||
//StaticJsonDocument<JSON_BUFFER_SIZE> docForExport;
|
||||
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE>* getLocalItemsAsJSON() {
|
||||
docForExport.clear();
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->iAmLocal) docForExport[(*it)->getID()] = (*it)->getValue();
|
||||
}
|
||||
// StaticJsonDocument<JSON_BUFFER_SIZE>* getLocalItemsAsJSON() {
|
||||
// docForExport.clear();
|
||||
// for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
// if ((*it)->iAmLocal) docForExport[(*it)->getID()] = (*it)->getValue();
|
||||
// }
|
||||
|
||||
return &docForExport;
|
||||
}
|
||||
// return &docForExport;
|
||||
// }
|
||||
@@ -28,6 +28,9 @@ class AnalogAdc : public IoTItem {
|
||||
AnalogAdc(String parameters) : IoTItem(parameters) {
|
||||
_pin = jsonReadInt(parameters, "pin");
|
||||
_avgSteps = jsonReadInt(parameters, "avgSteps");
|
||||
if (!_avgSteps) {
|
||||
jsonRead(parameters, F("int"), _interval, false);
|
||||
}
|
||||
_avgSumm = 0;
|
||||
_avgCount = 0;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
"moduleDesc": "Позволяет получить текущее значение на аналоговом GPIO или усредненное для avgSteps измерений каждого вызова loop.",
|
||||
"propInfo": {
|
||||
"pin": "Аналоговый GPIO номер, к которому подключен датчик.",
|
||||
"avgSteps": "Количество считываний для усреднения. При <=1, считывается одно значение за каждый период опроса.",
|
||||
"int": "Количество секунд между опросами датчика."
|
||||
"avgSteps": "Количество считываний для усреднения. При =1, считывается одно значение за каждый период опроса., при =0, int считается в миллисекундах",
|
||||
"int": "Количество секунд между опросами датчика, если avgSteps > 0. Установите avgSteps = 0 и int будет считаться в миллисекундах (ВНИМАНИЕ! генерация событий чаще секунды может привести к нестабильности системы.)"
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
|
||||
@@ -92,7 +92,7 @@ class UART : public IoTItem {
|
||||
|
||||
void onRegEvent(IoTItem* eventItem) {
|
||||
if (!_myUART || !eventItem) return;
|
||||
|
||||
int indexOf_;
|
||||
String printStr = "";
|
||||
switch (_eventFormat) {
|
||||
case 0: return; // не указан формат, значит не следим за событиями
|
||||
@@ -105,7 +105,7 @@ class UART : public IoTItem {
|
||||
|
||||
case 2: // формат событий для Nextion ID=Value0xFF0xFF0xFF
|
||||
printStr += eventItem->getID();
|
||||
int indexOf_ = printStr.indexOf("_");
|
||||
indexOf_ = printStr.indexOf("_");
|
||||
//Serial.println(printStr + " fff " + indexOf_);
|
||||
if (indexOf_ == -1) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol
|
||||
|
||||
@@ -126,9 +126,86 @@ class UART : public IoTItem {
|
||||
|
||||
uartPrintFFF(printStr);
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
virtual void loop() {
|
||||
uartHandle();
|
||||
}
|
||||
|
||||
@@ -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, которые влияют на передаваемый формат."
|
||||
"eventFormat": "Выбор формата обмена сообщениями с другими контроллерами. =0 - не указан формат, значит не следим за событиями, =1 - формат событий IoTM с использованием json, =2 - формат событий для Nextion отправка событий: ID.val=Value0xFF0xFF0xFF прием ордеров: ID=Value. Отправляться будут события тех элементов, которые имеют суффикс в ИД _val или _txt, которые влияют на передаваемый формат, =3 - формат событий для экранов Dwin. Отправляться будут события тех элементов, которые имеют суффикс в ИД с указанием адреса VP для записи значения, например ID_5000. Пока поддерживается только вывод целых чисел, значения кнопки и текст."
|
||||
},
|
||||
"retInfo": "Содержит полученное последнее по UART сообщение.",
|
||||
"funcInfo": [
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"title": "Таймер обратного отсчета",
|
||||
"moduleDesc": "Добавляет инструмент таймеров обратного отсчета для организации периодичных операций или логических конструкций. Часто используется как вспомогательный элемент для автоматизации.",
|
||||
"propInfo": {
|
||||
"int": "Задает размер в миллисекундах (1000 = 1сек) одного шага(тика) таймера.",
|
||||
"int": "Задает размер в секундах одного шага(тика) таймера.",
|
||||
"countDown": "Начальное значение таймера, с которого начинается обратный отсчет. countDown=0 - бесконечный счет (имеет смысл при ticker=1, иначе таймер будет выключен), countDown=-1 - отключает таймер совсем (используется для запуска системы с выключенным таймером)",
|
||||
"ticker": "Генерировать(1) или нет(0) события при каждом тике таймера.",
|
||||
"repeat": "Сбрасывать(1) или нет(0) таймер в начальное состояние при достижении нуля.",
|
||||
|
||||
@@ -22,7 +22,7 @@ bool jsonRead(const String& json, String key, long& value, bool e) {
|
||||
return false;
|
||||
} else if (!doc.containsKey(key)) {
|
||||
if (e) {
|
||||
SerialPrint("E", F("jsonRead"), key + " missing");
|
||||
SerialPrint("E", F("jsonRead"), key + " missing in " + json);
|
||||
jsonErrorDetected();
|
||||
}
|
||||
return false;
|
||||
@@ -42,7 +42,7 @@ bool jsonRead(const String& json, String key, float& value, bool e) {
|
||||
return false;
|
||||
} else if (!doc.containsKey(key)) {
|
||||
if (e) {
|
||||
SerialPrint("E", F("jsonRead"), key + " missing");
|
||||
SerialPrint("E", F("jsonRead"), key + " missing in " + json);
|
||||
jsonErrorDetected();
|
||||
}
|
||||
return false;
|
||||
@@ -62,7 +62,7 @@ bool jsonRead(const String& json, String key, String& value, bool e) {
|
||||
return false;
|
||||
} else if (!doc.containsKey(key)) {
|
||||
if (e) {
|
||||
SerialPrint("E", F("jsonRead"), key + " missing");
|
||||
SerialPrint("E", F("jsonRead"), key + " missing in " + json);
|
||||
jsonErrorDetected();
|
||||
}
|
||||
return false;
|
||||
@@ -89,7 +89,7 @@ bool jsonRead(const String& json, String key, int& value, bool e) {
|
||||
return false;
|
||||
} else if (!doc.containsKey(key)) {
|
||||
if (e) {
|
||||
SerialPrint("E", F("jsonRead"), key + " missing");
|
||||
SerialPrint("E", F("jsonRead"), key + " missing in " + json);
|
||||
jsonErrorDetected();
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -21,7 +21,7 @@ void SerialPrint(const String& errorLevel, const String& module, const String& m
|
||||
cleanString(tosend);
|
||||
// создаем событие об ошибке для возможной реакции в сценарии
|
||||
if (itemId != "") {
|
||||
createItemFromNet(itemId + F("_onError"), tosend, -4);
|
||||
createItemFromNet(itemId + F("_onError"), tosend, 1);
|
||||
} else {
|
||||
// createItemFromNet("onError", tosend, -4);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user