diff --git a/data_svelte/myProfile.json b/data_svelte/myProfile.json index d98d0798..0170a5e1 100644 --- a/data_svelte/myProfile.json +++ b/data_svelte/myProfile.json @@ -3,14 +3,8 @@ "name": "IoTmanagerVer4", "apssid": "IoTmanager", "appass": "", - "routerssid": [ - "iot", - "wifi" - ], - "routerpass": [ - "hostel3333", - "pswd" - ], + "routerssid": "iot", + "routerpass": "hostel3333", "timezone": 2, "ntp": "pool.ntp.org", "weblogin": "admin", diff --git a/data_svelte/settings.json b/data_svelte/settings.json index 376ea5c9..297019c9 100644 --- a/data_svelte/settings.json +++ b/data_svelte/settings.json @@ -2,14 +2,8 @@ "name": "IoTmanagerVer4", "apssid": "IoTmanager", "appass": "", - "routerssid": [ - "iot", - "wifi" - ], - "routerpass": [ - "hostel3333", - "pswd" - ], + "routerssid": "iot", + "routerpass": "hostel3333", "timezone": 2, "ntp": "pool.ntp.org", "weblogin": "admin", diff --git a/include/classes/IoTItem.h b/include/classes/IoTItem.h index d727a9a1..bb64a69f 100644 --- a/include/classes/IoTItem.h +++ b/include/classes/IoTItem.h @@ -63,6 +63,7 @@ class IoTItem { virtual void onMqttRecive(String& topic, String& msg); virtual void onMqttWsAppConnectEvent(); virtual void onModuleOrder(String& key, String& value); + virtual void onTrackingValue(IoTItem* item); // момент, когда ядро заметило изменение отслеживаемого значения // делаем доступным модулям отправку сообщений в телеграм virtual void sendTelegramMsg(bool often, String msg); @@ -74,6 +75,8 @@ class IoTItem { virtual void clearHistory(); virtual void setTodayDate(); + bool isTracking(IoTItem* item); // проверка на отслеживание + protected: bool _needSave = false; // признак необходимости сохранять и загружать значение элемента на flash String _subtype = ""; @@ -93,6 +96,8 @@ class IoTItem { int _numDigits = 1; // количество целых значений, не значимые позиции заменяются нулем в строковом формате bool _global = false; // характеристика айтема, что ему нужно слать и принимать события из внешнего мира + + IoTValue* _trackingValue = nullptr; // указатель на значение родительского элемента изменение которого отслеживается }; IoTItem* findIoTItem(const String& name); // поиск экземпляра элемента модуля по имени diff --git a/src/EventsAndOrders.cpp b/src/EventsAndOrders.cpp index 20416471..4099d1a2 100644 --- a/src/EventsAndOrders.cpp +++ b/src/EventsAndOrders.cpp @@ -51,16 +51,21 @@ void handleEvent() { if (eventBuf.length()) { String event = selectToMarker(eventBuf, ","); SerialPrint("i", F("EVENT"), event); - String enentIdName = selectToMarker(event, " "); + String eventIdName = selectToMarker(event, " "); + IoTItem* eventIoTItem = findIoTItem(eventIdName); + + if (eventIoTItem) + // распространяем событие через хуки + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + (*it)->onRegEvent(eventIoTItem); // прямой хук - // распространяем событие через хуки - for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { - (*it)->onRegEvent(findIoTItem(enentIdName)); - } + // вызов хука при условии отслеживания изменения + if ((*it)->isTracking(eventIoTItem)) (*it)->onTrackingValue(eventIoTItem); + } //здесь нужно пропускать данное событие через условия сценариев - //и если оно есть в условии сценария и совподает - iotScen.exec(enentIdName); + //и если оно есть в условии сценария и совпадает + iotScen.exec(eventIdName); eventBuf = deleteBeforeDelimiter(eventBuf, ","); } diff --git a/src/WsServer.cpp b/src/WsServer.cpp index db7bbd35..c63a3429 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -4,449 +4,456 @@ extern IoTScenario iotScen; #ifdef STANDARD_WEB_SOCKETS void standWebSocketsInit() { - standWebSocket.begin(); - standWebSocket.onEvent(webSocketEvent); - SerialPrint("i", "WS", "WS server initialized"); + standWebSocket.begin(); + standWebSocket.onEvent(webSocketEvent); + SerialPrint("i", "WS", "WS server initialized"); } void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) { - switch (type) { - case WStype_ERROR: { - Serial.printf("[%u] Error!\n", num); - } break; + switch (type) { + case WStype_ERROR: { + Serial.printf("[%u] Error!\n", num); + } break; - case WStype_DISCONNECTED: { - Serial.printf("[%u] Disconnected!\n", num); - } break; + case WStype_DISCONNECTED: { + Serial.printf("[%u] Disconnected!\n", num); + } break; - case WStype_CONNECTED: { - // IPAddress ip = standWebSocket.remoteIP(num); - SerialPrint("i", "WS " + String(num), "WS client connected"); - if (num >= 3) { - SerialPrint("E", "WS", "Too many clients, connection closed!!!"); - jsonWriteInt(errorsHeapJson, "wse1", 1); - standWebSocket.close(); - standWebSocketsInit(); - } - // Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], - // ip[1], ip[2], ip[3], payload); standWebSocket.sendTXT(num, - // "Connected"); - } break; - - case WStype_TEXT: { - bool endOfHeaderFound = false; - size_t maxAllowedHeaderSize = - 15; // максимальное количество символов заголовка - size_t headerLenth = 0; - String headerStr; - for (size_t i = 0; i <= maxAllowedHeaderSize; i++) { - headerLenth++; - char s = (char)payload[i]; - headerStr += s; - if (s == '|') { - endOfHeaderFound = true; - break; - } - } - if (!endOfHeaderFound) { - SerialPrint("E", "WS " + String(num), "Package without header"); - } - - //----------------------------------------------------------------------// - // Страница веб интерфейса dashboard - //----------------------------------------------------------------------// - - // публикация всех виджетов - if (headerStr == "/|") { - sendFileToWsByFrames("/layout.json", "layout", "", num, - WEB_SOCKETS_FRAME_SIZE); - } - - if (headerStr == "/params|") { - // публикация всех статус сообщений при подключении svelte приложения - String params = "{}"; - for (std::list::iterator it = IoTItems.begin(); - it != IoTItems.end(); ++it) { - if ((*it)->getSubtype() != "Loging") { - if ((*it)->getSubtype() != "LogingDaily") { - if ((*it)->iAmLocal) - jsonWriteStr(params, (*it)->getID(), (*it)->getValue()); + case WStype_CONNECTED: { + // IPAddress ip = standWebSocket.remoteIP(num); + SerialPrint("i", "WS " + String(num), "WS client connected"); + if (num >= 3) { + SerialPrint("E", "WS", "Too many clients, connection closed!!!"); + jsonWriteInt(errorsHeapJson, "wse1", 1); + standWebSocket.close(); + standWebSocketsInit(); } - } - } - sendStringToWs("params", params, num); + // Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], + // ip[1], ip[2], ip[3], payload); standWebSocket.sendTXT(num, + // "Connected"); + } break; - // генерация события подключения в модулях - for (std::list::iterator it = IoTItems.begin(); - it != IoTItems.end(); ++it) { - if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent(); - } - } + case WStype_TEXT: { + bool endOfHeaderFound = false; + size_t maxAllowedHeaderSize = + 15; // максимальное количество символов заголовка + size_t headerLenth = 0; + String headerStr; + for (size_t i = 0; i <= maxAllowedHeaderSize; i++) { + headerLenth++; + char s = (char)payload[i]; + headerStr += s; + if (s == '|') { + endOfHeaderFound = true; + break; + } + } + if (!endOfHeaderFound) { + SerialPrint("E", "WS " + String(num), "Package without header"); + } - // отвечаем на запрос графиков - if (headerStr == "/charts|") { - // обращение к логированию из ядра - // отправка данных графиков только в выбранный сокет - for (std::list::iterator it = IoTItems.begin(); - it != IoTItems.end(); ++it) { - // сбрасываем даты графиков - // if ((*it)->getID().endsWith("-date")) { - // (*it)->setTodayDate(); - // } - if ((*it)->getSubtype() == "Loging" || "LogingDaily") { - (*it)->setPublishDestination(TO_WS, num); - (*it)->publishValue(); - } - } - } + //----------------------------------------------------------------------// + // Страница веб интерфейса dashboard + //----------------------------------------------------------------------// - //----------------------------------------------------------------------// - // Страница веб интерфейса configutation - //----------------------------------------------------------------------// + // публикация всех виджетов + if (headerStr == "/|") { + sendFileToWsByFrames("/layout.json", "layout", "", num, + WEB_SOCKETS_FRAME_SIZE); + } - // отвечаем данными на запрос страницы - if (headerStr == "/config|") { - sendFileToWsByFrames("/items.json", "itemsj", "", num, - WEB_SOCKETS_FRAME_SIZE); - sendFileToWsByFrames("/widgets.json", "widget", "", num, - WEB_SOCKETS_FRAME_SIZE); - sendFileToWsByFrames("/config.json", "config", "", num, - WEB_SOCKETS_FRAME_SIZE); - sendFileToWsByFrames("/scenario.txt", "scenar", "", num, - WEB_SOCKETS_FRAME_SIZE); - sendStringToWs("settin", settingsFlashJson, num); - } + if (headerStr == "/params|") { + // публикация всех статус сообщений при подключении svelte приложения + String params = "{}"; + for (std::list::iterator it = IoTItems.begin(); + it != IoTItems.end(); ++it) { + if ((*it)->getSubtype() != "Loging") { + if ((*it)->getSubtype() != "LogingDaily") { + if ((*it)->iAmLocal) + jsonWriteStr(params, (*it)->getID(), (*it)->getValue()); + } + } + } + sendStringToWs("params", params, num); - // обработка кнопки сохранить - if (headerStr == "/gifnoc|") { - writeFileUint8tByFrames("config.json", payload, length, headerLenth, - 256); - } - if (headerStr == "/tuoyal|") { - writeFileUint8tByFrames("layout.json", payload, length, headerLenth, - 256); - } - if (headerStr == "/oiranecs|") { - writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, - 256); - clearConfigure(); - configure("/config.json"); - iotScen.loadScenario("/scenario.txt"); - // создаем событие завершения конфигурирования для возможности - // выполнения блока кода при загрузке - createItemFromNet("onStart", "1", 1); - } + // генерация события подключения в модулях + for (std::list::iterator it = IoTItems.begin(); + it != IoTItems.end(); ++it) { + if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent(); + } + } - //----------------------------------------------------------------------// - // Страница веб интерфейса connection - //----------------------------------------------------------------------// + // отвечаем на запрос графиков + if (headerStr == "/charts|") { + // обращение к логированию из ядра + // отправка данных графиков только в выбранный сокет + for (std::list::iterator it = IoTItems.begin(); + it != IoTItems.end(); ++it) { + // сбрасываем даты графиков + // if ((*it)->getID().endsWith("-date")) { + // (*it)->setTodayDate(); + // } + if ((*it)->getSubtype() == "Loging" || "LogingDaily") { + (*it)->setPublishDestination(TO_WS, num); + (*it)->publishValue(); + } + } + } - // отвечаем данными на запрос страницы - if (headerStr == "/connection|") { - sendStringToWs("settin", settingsFlashJson, num); - sendStringToWs("ssidli", ssidListHeapJson, num); - sendStringToWs("errors", errorsHeapJson, num); - // запуск асинхронного сканирования wifi сетей при переходе на страницу - // соединений RouterFind(jsonReadStr(settingsFlashJson, - // F("routerssid"))); - } + //----------------------------------------------------------------------// + // Страница веб интерфейса configutation + //----------------------------------------------------------------------// - // обработка кнопки сохранить settings.json - if (headerStr == "/sgnittes|") { - writeUint8tToString(payload, length, headerLenth, settingsFlashJson); - writeFileUint8tByFrames("settings.json", payload, length, headerLenth, - 256); - sendStringToWs("errors", errorsHeapJson, num); - // если не было создано приема данных по udp - то создадим его - addThisDeviceToList(); - } + // отвечаем данными на запрос страницы + if (headerStr == "/config|") { + sendFileToWsByFrames("/items.json", "itemsj", "", num, + WEB_SOCKETS_FRAME_SIZE); + sendFileToWsByFrames("/widgets.json", "widget", "", num, + WEB_SOCKETS_FRAME_SIZE); + sendFileToWsByFrames("/config.json", "config", "", num, + WEB_SOCKETS_FRAME_SIZE); + sendFileToWsByFrames("/scenario.txt", "scenar", "", num, + WEB_SOCKETS_FRAME_SIZE); + sendStringToWs("settin", settingsFlashJson, num); + } - // обработка кнопки сохранить настройки mqtt - if (headerStr == "/mqtt|") { - sendStringToWs("settin", settingsFlashJson, - num); // отправляем в ответ новые полученные настройки - handleMqttStatus(false, 8); // меняем статус на неопределенный - mqttReconnect(); // начинаем переподключение - sendStringToWs("errors", errorsHeapJson, - num); // отправляем что статус неопределен - sendStringToWs("ssidli", ssidListHeapJson, num); - } + // обработка кнопки сохранить + if (headerStr == "/gifnoc|") { + writeFileUint8tByFrames("config.json", payload, length, headerLenth, + 256); + } + if (headerStr == "/tuoyal|") { + writeFileUint8tByFrames("layout.json", payload, length, headerLenth, + 256); + } + if (headerStr == "/oiranecs|") { + writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, + 256); + clearConfigure(); + configure("/config.json"); + iotScen.loadScenario("/scenario.txt"); + // создаем событие завершения конфигурирования для возможности + // выполнения блока кода при загрузке + createItemFromNet("onStart", "1", 1); + } - // запуск асинхронного сканирования wifi сетей при нажатии выпадающего - // списка - if (headerStr == "/scan|") { - std::vector jArray; - jsonReadArray(settingsFlashJson, "routerssid", jArray); - RouterFind(jArray); - sendStringToWs("ssidli", ssidListHeapJson, num); - } + //----------------------------------------------------------------------// + // Страница веб интерфейса connection + //----------------------------------------------------------------------// - //----------------------------------------------------------------------// - // Страница веб интерфейса list - //----------------------------------------------------------------------// + // отвечаем данными на запрос страницы + if (headerStr == "/connection|") { + sendStringToWs("settin", settingsFlashJson, num); + sendStringToWs("ssidli", ssidListHeapJson, num); + sendStringToWs("errors", errorsHeapJson, num); + // запуск асинхронного сканирования wifi сетей при переходе на страницу + // соединений RouterFind(jsonReadStr(settingsFlashJson, + // F("routerssid"))); + } - // отвечаем данными на запрос страницы list - if (headerStr == "/list|") { - sendStringToWs("settin", settingsFlashJson, num); - // отправим список устройств в зависимости от того что выбрал user - // sendDeviceList(num); - } + // обработка кнопки сохранить settings.json + if (headerStr == "/sgnittes|") { + writeUint8tToString(payload, length, headerLenth, settingsFlashJson); + writeFileUint8tByFrames("settings.json", payload, length, headerLenth, + 256); + sendStringToWs("errors", errorsHeapJson, num); + // если не было создано приема данных по udp - то создадим его + addThisDeviceToList(); + } - // отвечаем на запрос списка устройств (это отдельный запрос который - // делает приложение при подключении) - if (headerStr == "/devlist|") { - // отправим список устройств в зависимости от того что выбрал user - sendDeviceList(num); - } + // обработка кнопки сохранить настройки mqtt + if (headerStr == "/mqtt|") { + sendStringToWs("settin", settingsFlashJson, + num); // отправляем в ответ новые полученные настройки + handleMqttStatus(false, 8); // меняем статус на неопределенный + mqttReconnect(); // начинаем переподключение + sendStringToWs("errors", errorsHeapJson, + num); // отправляем что статус неопределен + sendStringToWs("ssidli", ssidListHeapJson, num); + } - // сохраняем данные листа - if (headerStr == "/tsil|") { - writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, - 256); - } + // запуск асинхронного сканирования wifi сетей при нажатии выпадающего + // списка + if (headerStr == "/scan|") { + std::vector jArray; + jsonReadArray(settingsFlashJson, "routerssid", jArray); + RouterFind(jArray); + sendStringToWs("ssidli", ssidListHeapJson, num); + } - //----------------------------------------------------------------------// - // Страница веб интерфейса system - //----------------------------------------------------------------------// + //----------------------------------------------------------------------// + // Страница веб интерфейса list + //----------------------------------------------------------------------// - // отвечаем данными на запрос страницы - if (headerStr == "/system|") { - sendStringToWs("errors", errorsHeapJson, num); - sendStringToWs("settin", settingsFlashJson, num); - } + // отвечаем данными на запрос страницы list + if (headerStr == "/list|") { + sendStringToWs("settin", settingsFlashJson, num); + // отправим список устройств в зависимости от того что выбрал user + // sendDeviceList(num); + } - //----------------------------------------------------------------------// - // Страница веб интерфейса dev - //----------------------------------------------------------------------// - if (headerStr == "/dev|") { - sendStringToWs("errors", errorsHeapJson, num); - sendStringToWs("settin", settingsFlashJson, num); - sendFileToWsByFrames("/config.json", "config", "", num, - WEB_SOCKETS_FRAME_SIZE); - sendFileToWsByFrames("/items.json", "itemsj", "", num, - WEB_SOCKETS_FRAME_SIZE); - // sendFileToWsByFrames("/layout.json", "layout", "", num, - // WEB_SOCKETS_FRAME_SIZE); - } + // отвечаем на запрос списка устройств (это отдельный запрос который + // делает приложение при подключении) + if (headerStr == "/devlist|") { + // отправим список устройств в зависимости от того что выбрал user + sendDeviceList(num); + } - if (headerStr == "/test|") { - } + // сохраняем данные листа + if (headerStr == "/tsil|") { + writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, + 256); + } - //----------------------------------------------------------------------// - // отдельные команды веб интерфейса - //----------------------------------------------------------------------// + //----------------------------------------------------------------------// + // Страница веб интерфейса system + //----------------------------------------------------------------------// - // переписать любое поле в errors json - if (headerStr == "/rorre|") { - writeUint8tValueToJsonString(payload, length, headerLenth, - errorsHeapJson); - } + // отвечаем данными на запрос страницы + if (headerStr == "/system|") { + sendStringToWs("errors", errorsHeapJson, num); + sendStringToWs("settin", settingsFlashJson, num); + } - // команда перезагрузки esp - if (headerStr == "/reboot|") { - ESP.restart(); - } + //----------------------------------------------------------------------// + // Страница веб интерфейса dev + //----------------------------------------------------------------------// + if (headerStr == "/dev|") { + sendStringToWs("errors", errorsHeapJson, num); + sendStringToWs("settin", settingsFlashJson, num); + sendFileToWsByFrames("/config.json", "config", "", num, + WEB_SOCKETS_FRAME_SIZE); + sendFileToWsByFrames("/items.json", "itemsj", "", num, + WEB_SOCKETS_FRAME_SIZE); + // sendFileToWsByFrames("/layout.json", "layout", "", num, + // WEB_SOCKETS_FRAME_SIZE); + } - // команда очистки всех логов esp - if (headerStr == "/clean|") { - cleanLogs(); - } + //----------------------------------------------------------------------// + // Страница веб интерфейса update + //----------------------------------------------------------------------// + if (headerStr == "/profile|") { + sendFileToWsByFrames("/myProfile.json", "prfile", "", num, + WEB_SOCKETS_FRAME_SIZE); + } - // команда обновления прошивки esp - if (headerStr == "/update|") { - upgrade_firmware(3); - } + //----------------------------------------------------------------------// + // отдельные команды веб интерфейса + //----------------------------------------------------------------------// - // Прием команд control c dashboard - if (headerStr == "/control|") { - String msg; - writeUint8tToString(payload, length, headerLenth, msg); - String key = selectFromMarkerToMarker(msg, "/", 0); - String value = selectFromMarkerToMarker(msg, "/", 1); - generateOrder(key, value); - SerialPrint( - "i", F("=>WS"), - "Msg from svelte web, WS No: " + String(num) + ", msg: " + msg); - } + // переписать любое поле в errors json + if (headerStr == "/rorre|") { + writeUint8tValueToJsonString(payload, length, headerLenth, + errorsHeapJson); + } - if (headerStr == "/tst|") { - standWebSocket.sendTXT(num, "/tstr|"); - } + // команда перезагрузки esp + if (headerStr == "/reboot|") { + ESP.restart(); + } - // получаем команду посланную из модуля - if (headerStr == "/order|") { - String json; - writeUint8tToString(payload, length, headerLenth, json); + // команда очистки всех логов esp + if (headerStr == "/clean|") { + cleanLogs(); + } - String id, key, value; - jsonRead(json, "id", id); - jsonRead(json, "key", key); - jsonRead(json, "value", value); + // команда обновления прошивки esp + if (headerStr == "/update|") { + upgrade_firmware(3); + } - SerialPrint("i", F("=>WS"), "Msg from module, id: " + id); + // Прием команд control c dashboard + if (headerStr == "/control|") { + String msg; + writeUint8tToString(payload, length, headerLenth, msg); + String key = selectFromMarkerToMarker(msg, "/", 0); + String value = selectFromMarkerToMarker(msg, "/", 1); + generateOrder(key, value); + SerialPrint( + "i", F("=>WS"), + "Msg from svelte web, WS No: " + String(num) + ", msg: " + msg); + } - for (std::list::iterator it = IoTItems.begin(); - it != IoTItems.end(); ++it) { - if ((*it)->getID() == id) { - (*it)->onModuleOrder(key, value); - } - } - } + if (headerStr == "/tst|") { + standWebSocket.sendTXT(num, "/tstr|"); + } - } break; + // получаем команду посланную из модуля + if (headerStr == "/order|") { + String json; + writeUint8tToString(payload, length, headerLenth, json); - case WStype_BIN: { - Serial.printf("[%u] get binary length: %u\n", num, length); - // hexdump(payload, length); - // standWebSocket.sendBIN(num, payload, length); - } break; + String id, key, value; + jsonRead(json, "id", id); + jsonRead(json, "key", key); + jsonRead(json, "value", value); - case WStype_FRAGMENT_TEXT_START: { - Serial.printf("[%u] fragment test start: %u\n", num, length); - } break; + SerialPrint("i", F("=>WS"), "Msg from module, id: " + id); - case WStype_FRAGMENT_BIN_START: { - Serial.printf("[%u] fragment bin start: %u\n", num, length); - } break; + for (std::list::iterator it = IoTItems.begin(); + it != IoTItems.end(); ++it) { + if ((*it)->getID() == id) { + (*it)->onModuleOrder(key, value); + } + } + } - case WStype_FRAGMENT: { - Serial.printf("[%u] fragment: %u\n", num, length); - } break; + } break; - case WStype_FRAGMENT_FIN: { - Serial.printf("[%u] fragment finish: %u\n", num, length); - } break; + case WStype_BIN: { + Serial.printf("[%u] get binary length: %u\n", num, length); + // hexdump(payload, length); + // standWebSocket.sendBIN(num, payload, length); + } break; - case WStype_PING: { - Serial.printf("[%u] ping: %u\n", num, length); - } break; + case WStype_FRAGMENT_TEXT_START: { + Serial.printf("[%u] fragment test start: %u\n", num, length); + } break; - case WStype_PONG: { - Serial.printf("[%u] pong: %u\n", num, length); - } break; + case WStype_FRAGMENT_BIN_START: { + Serial.printf("[%u] fragment bin start: %u\n", num, length); + } break; - default: { Serial.printf("[%u] not recognized: %u\n", num, length); } break; - } + case WStype_FRAGMENT: { + Serial.printf("[%u] fragment: %u\n", num, length); + } break; + + case WStype_FRAGMENT_FIN: { + Serial.printf("[%u] fragment finish: %u\n", num, length); + } break; + + case WStype_PING: { + Serial.printf("[%u] ping: %u\n", num, length); + } break; + + case WStype_PONG: { + Serial.printf("[%u] pong: %u\n", num, length); + } break; + + default: { + Serial.printf("[%u] not recognized: %u\n", num, length); + } break; + } } // публикация статус сообщений в ws (недостаток в том что делаем бродкаст всем // клиентам поднятым в свелте!!!) void publishStatusWs(const String& topic, const String& data) { - String path = mqttRootDevice + "/" + topic; - String json = "{}"; - jsonWriteStr(json, "status", data); - jsonWriteStr(json, "topic", path); - sendStringToWs("status", json, -1); + String path = mqttRootDevice + "/" + topic; + String json = "{}"; + jsonWriteStr(json, "status", data); + jsonWriteStr(json, "topic", path); + sendStringToWs("status", json, -1); } // публикация дополнительных json сообщений в ws void publishJsonWs(const String& topic, String& json) { - String path = mqttRootDevice + "/" + topic; - jsonWriteStr(json, "topic", path); - // TO DO отправка полей в веб - // sendStringToWs("status", json, -1); + String path = mqttRootDevice + "/" + topic; + jsonWriteStr(json, "topic", path); + // TO DO отправка полей в веб + // sendStringToWs("status", json, -1); } // данные которые мы отправляем в сокеты переодически void periodicWsSend() { - sendStringToWs("ssidli", ssidListHeapJson, -1); - sendStringToWs("errors", errorsHeapJson, -1); - // отправляем переодичестки только в авто режиме - if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { - sendStringToWs("devlis", devListHeapJson, -1); - } + sendStringToWs("ssidli", ssidListHeapJson, -1); + sendStringToWs("errors", errorsHeapJson, -1); + // отправляем переодичестки только в авто режиме + if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { + sendStringToWs("devlis", devListHeapJson, -1); + } } #ifdef ESP32 void hexdump(const void* mem, uint32_t len, uint8_t cols = 16) { - const uint8_t* src = (const uint8_t*)mem; - Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, - len, len); - for (uint32_t i = 0; i < len; i++) { - if (i % cols == 0) { - Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); + const uint8_t* src = (const uint8_t*)mem; + Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, + len, len); + for (uint32_t i = 0; i < len; i++) { + if (i % cols == 0) { + Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); + } + Serial.printf("%02X ", *src); + src++; } - Serial.printf("%02X ", *src); - src++; - } - Serial.printf("\n"); + Serial.printf("\n"); } #endif #endif void sendFileToWsByFrames(const String& filename, const String& header, const String& json, int client_id, size_t frameSize) { - if (header.length() != 6) { - SerialPrint("E", "FS", F("wrong header size")); - return; - } - - auto path = filepath(filename); - auto file = FileFS.open(path, "r"); - if (!file) { - SerialPrint("E", "FS", F("reed file error")); - return; - } - - size_t totalSize = file.size(); - // Serial.println("Send file '" + String(filename) + "', file size: " + - // String(totalSize)); - - char buf[32]; - sprintf(buf, "%04d", json.length() + 12); - String data = header + "|" + String(buf) + "|" + json; - - size_t headerSize = data.length(); - auto frameBuf = new uint8_t[frameSize]; - size_t maxPayloadSize = frameSize - headerSize; - uint8_t* payloadBuf = nullptr; - - int i = 0; - while (file.available()) { - if (i == 0) { - data.toCharArray((char*)frameBuf, frameSize); - payloadBuf = &frameBuf[headerSize]; - } else { - maxPayloadSize = frameSize; - headerSize = 0; - payloadBuf = &frameBuf[0]; + if (header.length() != 6) { + SerialPrint("E", "FS", F("wrong header size")); + return; } - size_t payloadSize = file.read(payloadBuf, maxPayloadSize); - if (payloadSize) { - size_t size = headerSize + payloadSize; - - bool fin = false; - if (size == frameSize) { - fin = false; - } else { - fin = true; - } - - bool continuation = false; - if (i == 0) { - continuation = false; - } else { - continuation = true; - } - - // Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: - // " + String(size) + " fin: " + String(fin) + " cnt: " + - // String(continuation)); - - if (client_id == -1) { - standWebSocket.broadcastBIN(frameBuf, size, fin, continuation); - - } else { - standWebSocket.sendBIN(client_id, frameBuf, size, fin, continuation); - } + auto path = filepath(filename); + auto file = FileFS.open(path, "r"); + if (!file) { + SerialPrint("E", "FS", F("reed file error")); + return; } - i++; - } - payloadBuf = &frameBuf[0]; - delete[] payloadBuf; - file.close(); + + size_t totalSize = file.size(); + // Serial.println("Send file '" + String(filename) + "', file size: " + + // String(totalSize)); + + char buf[32]; + sprintf(buf, "%04d", json.length() + 12); + String data = header + "|" + String(buf) + "|" + json; + + size_t headerSize = data.length(); + auto frameBuf = new uint8_t[frameSize]; + size_t maxPayloadSize = frameSize - headerSize; + uint8_t* payloadBuf = nullptr; + + int i = 0; + while (file.available()) { + if (i == 0) { + data.toCharArray((char*)frameBuf, frameSize); + payloadBuf = &frameBuf[headerSize]; + } else { + maxPayloadSize = frameSize; + headerSize = 0; + payloadBuf = &frameBuf[0]; + } + + size_t payloadSize = file.read(payloadBuf, maxPayloadSize); + if (payloadSize) { + size_t size = headerSize + payloadSize; + + bool fin = false; + if (size == frameSize) { + fin = false; + } else { + fin = true; + } + + bool continuation = false; + if (i == 0) { + continuation = false; + } else { + continuation = true; + } + + // Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: + // " + String(size) + " fin: " + String(fin) + " cnt: " + + // String(continuation)); + + if (client_id == -1) { + standWebSocket.broadcastBIN(frameBuf, size, fin, continuation); + + } else { + standWebSocket.sendBIN(client_id, frameBuf, size, fin, continuation); + } + } + i++; + } + payloadBuf = &frameBuf[0]; + delete[] payloadBuf; + file.close(); } void sendStringToWs(const String& header, String& payload, int client_id) { @@ -474,16 +481,16 @@ void sendStringToWs(const String& header, String& payload, int client_id) { } void sendDeviceList(uint8_t num) { - if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { - // если включен автопоиск то отдаем список из оперативной памяти - SerialPrint("i", "FS", "heap list"); - sendStringToWs("devlis", devListHeapJson, num); - } else { - // если выключен автопоиск то отдаем список из флешь памяти - sendFileToWsByFrames("/devlist.json", "devlis", "", num, - WEB_SOCKETS_FRAME_SIZE); - SerialPrint("i", "FS", "flash list"); - } + if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { + // если включен автопоиск то отдаем список из оперативной памяти + SerialPrint("i", "FS", "heap list"); + sendStringToWs("devlis", devListHeapJson, num); + } else { + // если выключен автопоиск то отдаем список из флешь памяти + sendFileToWsByFrames("/devlist.json", "devlis", "", num, + WEB_SOCKETS_FRAME_SIZE); + SerialPrint("i", "FS", "flash list"); + } } int getNumWSClients() { diff --git a/src/classes/IoTItem.cpp b/src/classes/IoTItem.cpp index 50678390..3df79e82 100644 --- a/src/classes/IoTItem.cpp +++ b/src/classes/IoTItem.cpp @@ -34,6 +34,13 @@ IoTItem::IoTItem(const String& parameters) { jsonRead(parameters, F("needSave"), _needSave, false); if (_needSave && jsonRead(valuesFlashJson, _id, valAsStr, false)) // пробуем достать из сохранения значение элемента, если указано, что нужно сохранять setValue(valAsStr, false); + + // проверяем нужно ли отслеживать значение другого элемента + String trackingID = ""; + IoTItem* item = nullptr; + if (jsonRead(parameters, F("trackingID"), trackingID, false) && (item = findIoTItem(trackingID)) != nullptr) { + _trackingValue = &(item->value); + } } void IoTItem::suspendNextDoByInt(unsigned long _delay) { // 0 - force @@ -183,6 +190,13 @@ void IoTItem::onRegEvent(IoTItem* item) {} void IoTItem::onMqttRecive(String& topic, String& msg) {} void IoTItem::onMqttWsAppConnectEvent() {} void IoTItem::onModuleOrder(String& key, String& value) {} +void IoTItem::onTrackingValue(IoTItem* item) { + setValue(item->getValue(), false); +} + +bool IoTItem::isTracking(IoTItem* item) { + return &(item->value) == _trackingValue; +} // делаем доступным модулям отправку сообщений в телеграм void IoTItem::sendTelegramMsg(bool often, String msg) {}