diff --git a/data_svelte/myProfile.json b/data_svelte/myProfile.json index 3ea1cffd..29a9155c 100644 --- a/data_svelte/myProfile.json +++ b/data_svelte/myProfile.json @@ -3,8 +3,8 @@ "name": "IoTmanagerVer4", "apssid": "IoTmanager", "appass": "", - "routerssid": "iot", - "routerpass": "hostel3333", + "routerssid": ["iot","wifi"], + "routerpass": ["hostel3333","pswd"], "timezone": 2, "ntp": "pool.ntp.org", "weblogin": "admin", @@ -32,6 +32,11 @@ "firmware": "0x00000", "littlefs": "0x300000" }, + { + "name": "esp8266_16mb", + "firmware": "0x00000", + "littlefs": "0x200000" + }, { "name": "esp32_4mb", "boot_app0": "0xe000", @@ -40,6 +45,14 @@ "partitions": "0x8000", "littlefs": "0x290000" }, + { + "name": "esp32_16mb", + "boot_app0": "0xe000", + "bootloader_qio_80m": "0x1000", + "firmware": "0x10000", + "partitions": "0x8000", + "littlefs": "0x910000" + }, { "name": "esp8266_1mb", "firmware": "0x00000000", diff --git a/data_svelte/settings.json b/data_svelte/settings.json index 297019c9..376ea5c9 100644 --- a/data_svelte/settings.json +++ b/data_svelte/settings.json @@ -2,8 +2,14 @@ "name": "IoTmanagerVer4", "apssid": "IoTmanager", "appass": "", - "routerssid": "iot", - "routerpass": "hostel3333", + "routerssid": [ + "iot", + "wifi" + ], + "routerpass": [ + "hostel3333", + "pswd" + ], "timezone": 2, "ntp": "pool.ntp.org", "weblogin": "admin", diff --git a/include/utils/JsonUtils.h b/include/utils/JsonUtils.h index c48fd725..89c7098b 100644 --- a/include/utils/JsonUtils.h +++ b/include/utils/JsonUtils.h @@ -1,31 +1,32 @@ -#pragma once - -#include "Global.h" - -extern String jsonReadStrDoc(DynamicJsonDocument& doc, String name); -extern void jsonWriteStrDoc(DynamicJsonDocument& doc, String name, String value); - -extern String jsonWriteStr(String& json, String name, String value, bool e = true); -extern String jsonWriteInt(String& json, String name, int value, bool e = true); -extern String jsonWriteFloat(String& json, String name, float value, bool e = true); -extern String jsonWriteBool(String& json, String name, boolean value, bool e = true); - -extern bool jsonRead(const String& json, String key, long& value, bool e = true); -extern bool jsonRead(const String& json, String key, float& value, bool e = true); -extern bool jsonRead(const String& json, String key, String& value, bool e = true); -extern bool jsonRead(const String& json, String key, bool& value, bool e = true); -extern bool jsonRead(const String& json, String key, int& value, bool e = true); - -extern String jsonReadStr(const String& json, String name, bool e = true); -extern int jsonReadInt(const String& json, String name, bool e = true); -long int jsonReadLInt(const String& json, String name, bool e=true); -extern boolean jsonReadBool(const String& json, String name, bool e = true); - -extern bool jsonWriteStr_(String& json, const String& name, const String& value, bool e = true); -extern bool jsonWriteBool_(String& json, const String& name, bool value, bool e = true); -extern bool jsonWriteInt_(String& json, const String& name, int value, bool e = true); -extern bool jsonWriteFloat_(String& json, const String& name, float value, bool e = true); -void writeUint8tValueToJsonString(uint8_t* payload, size_t length, size_t headerLenth, String& json); -extern bool jsonMergeObjects(String& json1, String& json2, bool e = true); -extern void jsonMergeDocs(JsonObject dest, JsonObjectConst src); -extern void jsonErrorDetected(); +#pragma once + +#include "Global.h" + +extern String jsonReadStrDoc(DynamicJsonDocument& doc, String name); +extern void jsonWriteStrDoc(DynamicJsonDocument& doc, String name, String value); + +extern String jsonWriteStr(String& json, String name, String value, bool e = true); +extern String jsonWriteInt(String& json, String name, int value, bool e = true); +extern String jsonWriteFloat(String& json, String name, float value, bool e = true); +extern String jsonWriteBool(String& json, String name, boolean value, bool e = true); + +extern bool jsonRead(const String& json, String key, long& value, bool e = true); +extern bool jsonRead(const String& json, String key, float& value, bool e = true); +extern bool jsonRead(const String& json, String key, String& value, bool e = true); +extern bool jsonRead(const String& json, String key, bool& value, bool e = true); +extern bool jsonRead(const String& json, String key, int& value, bool e = true); +extern bool jsonReadArray(const String& json, String key, JsonArray& jArray, bool e = true); + +extern String jsonReadStr(const String& json, String name, bool e = true); +extern int jsonReadInt(const String& json, String name, bool e = true); +long int jsonReadLInt(const String& json, String name, bool e=true); +extern boolean jsonReadBool(const String& json, String name, bool e = true); + +extern bool jsonWriteStr_(String& json, const String& name, const String& value, bool e = true); +extern bool jsonWriteBool_(String& json, const String& name, bool value, bool e = true); +extern bool jsonWriteInt_(String& json, const String& name, int value, bool e = true); +extern bool jsonWriteFloat_(String& json, const String& name, float value, bool e = true); +void writeUint8tValueToJsonString(uint8_t* payload, size_t length, size_t headerLenth, String& json); +extern bool jsonMergeObjects(String& json1, String& json2, bool e = true); +extern void jsonMergeDocs(JsonObject dest, JsonObjectConst src); +extern void jsonErrorDetected(); diff --git a/include/utils/WiFiUtils.h b/include/utils/WiFiUtils.h index 89bec1f4..538b40a1 100644 --- a/include/utils/WiFiUtils.h +++ b/include/utils/WiFiUtils.h @@ -1,12 +1,12 @@ -#pragma once - -#include "Global.h" -#include "MqttClient.h" - -// boolean isNetworkActive(); -inline boolean isNetworkActive() {return WiFi.status() == WL_CONNECTED;}; -void routerConnect(); -bool startAPMode(); -boolean RouterFind(String ssid); -uint8_t RSSIquality(); -extern void wifiSignalInit(); +#pragma once + +#include "Global.h" +#include "MqttClient.h" + +// boolean isNetworkActive(); +inline boolean isNetworkActive() {return WiFi.status() == WL_CONNECTED;}; +void routerConnect(); +bool startAPMode(); +boolean RouterFind(JsonArray jArray); +uint8_t RSSIquality(); +extern void wifiSignalInit(); diff --git a/myProfile.json b/myProfile.json index 4d42e658..29a9155c 100644 --- a/myProfile.json +++ b/myProfile.json @@ -3,8 +3,8 @@ "name": "IoTmanagerVer4", "apssid": "IoTmanager", "appass": "", - "routerssid": "iot", - "routerpass": "hostel3333", + "routerssid": ["iot","wifi"], + "routerpass": ["hostel3333","pswd"], "timezone": 2, "ntp": "pool.ntp.org", "weblogin": "admin", diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 7dd5c8ed..5ae98404 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -1,448 +1,451 @@ -#include "WsServer.h" -#include "classes/IoTScenario.h" -extern IoTScenario iotScen; - -#ifdef STANDARD_WEB_SOCKETS -void standWebSocketsInit() { - 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; - - 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()); - } - } - } - sendStringToWs("params", params, num); - - // генерация события подключения в модулях - for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { - if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent(); - } - } - - // отвечаем на запрос графиков - 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(); - } - } - } - - //----------------------------------------------------------------------// - // Страница веб интерфейса configutation - //----------------------------------------------------------------------// - - // отвечаем данными на запрос страницы - 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 == "/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); - } - - //----------------------------------------------------------------------// - // Страница веб интерфейса connection - //----------------------------------------------------------------------// - - // отвечаем данными на запрос страницы - if (headerStr == "/connection|") { - sendStringToWs("settin", settingsFlashJson, num); - sendStringToWs("ssidli", ssidListHeapJson, num); - sendStringToWs("errors", errorsHeapJson, num); - // запуск асинхронного сканирования wifi сетей при переходе на страницу соединений - // RouterFind(jsonReadStr(settingsFlashJson, F("routerssid"))); - } - - // обработка кнопки сохранить settings.json - if (headerStr == "/sgnittes|") { - writeUint8tToString(payload, length, headerLenth, settingsFlashJson); - writeFileUint8tByFrames("settings.json", payload, length, headerLenth, 256); - sendStringToWs("errors", errorsHeapJson, num); - // если не было создано приема данных по udp - то создадим его - addThisDeviceToList(); - } - - // обработка кнопки сохранить настройки mqtt - if (headerStr == "/mqtt|") { - sendStringToWs("settin", settingsFlashJson, num); // отправляем в ответ новые полученные настройки - handleMqttStatus(false, 8); // меняем статус на неопределенный - mqttReconnect(); // начинаем переподключение - sendStringToWs("errors", errorsHeapJson, num); // отправляем что статус неопределен - sendStringToWs("ssidli", ssidListHeapJson, num); - } - - // запуск асинхронного сканирования wifi сетей при нажатии выпадающего списка - if (headerStr == "/scan|") { - RouterFind(jsonReadStr(settingsFlashJson, F("routerssid"))); - sendStringToWs("ssidli", ssidListHeapJson, num); - } - - //----------------------------------------------------------------------// - // Страница веб интерфейса list - //----------------------------------------------------------------------// - - // отвечаем данными на запрос страницы list - if (headerStr == "/list|") { - sendStringToWs("settin", settingsFlashJson, num); - // отправим список устройств в зависимости от того что выбрал user - // sendDeviceList(num); - } - - // отвечаем на запрос списка устройств (это отдельный запрос который делает приложение при подключении) - if (headerStr == "/devlist|") { - // отправим список устройств в зависимости от того что выбрал user - sendDeviceList(num); - } - - // сохраняем данные листа - if (headerStr == "/tsil|") { - writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, 256); - } - - //----------------------------------------------------------------------// - // Страница веб интерфейса system - //----------------------------------------------------------------------// - - // отвечаем данными на запрос страницы - if (headerStr == "/system|") { - sendStringToWs("errors", errorsHeapJson, num); - sendStringToWs("settin", settingsFlashJson, 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 == "/test|") { - } - - //----------------------------------------------------------------------// - // отдельные команды веб интерфейса - //----------------------------------------------------------------------// - - // переписать любое поле в errors json - if (headerStr == "/rorre|") { - writeUint8tValueToJsonString(payload, length, headerLenth, errorsHeapJson); - } - - // команда перезагрузки esp - if (headerStr == "/reboot|") { - ESP.restart(); - } - - // команда очистки всех логов esp - if (headerStr == "/clean|") { - cleanLogs(); - } - - // команда обновления прошивки 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); - } - - if (headerStr == "/tst|") { - standWebSocket.sendTXT(num, "/tstr|"); - } - - // получаем команду посланную из модуля - if (headerStr == "/order|") { - String json; - writeUint8tToString(payload, length, headerLenth, json); - - String id, key, value; - jsonRead(json, "id", id); - jsonRead(json, "key", key); - jsonRead(json, "value", value); - - SerialPrint("i", F("=>WS"), "Msg from module, id: " + id); - - for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { - if ((*it)->getID() == id) { - (*it)->onModuleOrder(key, value); - } - } - } - - } 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_FRAGMENT_TEXT_START: { - Serial.printf("[%u] fragment test start: %u\n", num, length); - } break; - - case WStype_FRAGMENT_BIN_START: { - Serial.printf("[%u] fragment bin start: %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); -} - -// публикация дополнительных json сообщений в ws -void publishJsonWs(const String& topic, String& json) { - 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); - } -} - -#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); - } - Serial.printf("%02X ", *src); - src++; - } - 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]; - } - - 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) { - if (!(WiFi.softAPgetStationNum() || isNetworkActive())) { - return; - } - - if (header.length() != 6) { - SerialPrint("E", "FS", F("wrong header size")); - return; - } - - String msg = header + "|0012|" + payload; - size_t totalSize = msg.length(); - - char dataArray[totalSize]; - msg.toCharArray(dataArray, totalSize + 1); - if (client_id == -1) { - standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize); - } else { - standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize); - } -} - -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"); - } -} +#include "WsServer.h" +#include "classes/IoTScenario.h" +extern IoTScenario iotScen; + +#ifdef STANDARD_WEB_SOCKETS +void standWebSocketsInit() { + 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; + + 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()); + } + } + } + sendStringToWs("params", params, num); + + // генерация события подключения в модулях + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent(); + } + } + + // отвечаем на запрос графиков + 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(); + } + } + } + + //----------------------------------------------------------------------// + // Страница веб интерфейса configutation + //----------------------------------------------------------------------// + + // отвечаем данными на запрос страницы + 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 == "/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); + } + + //----------------------------------------------------------------------// + // Страница веб интерфейса connection + //----------------------------------------------------------------------// + + // отвечаем данными на запрос страницы + if (headerStr == "/connection|") { + sendStringToWs("settin", settingsFlashJson, num); + sendStringToWs("ssidli", ssidListHeapJson, num); + sendStringToWs("errors", errorsHeapJson, num); + // запуск асинхронного сканирования wifi сетей при переходе на страницу соединений + // RouterFind(jsonReadStr(settingsFlashJson, F("routerssid"))); + } + + // обработка кнопки сохранить settings.json + if (headerStr == "/sgnittes|") { + writeUint8tToString(payload, length, headerLenth, settingsFlashJson); + writeFileUint8tByFrames("settings.json", payload, length, headerLenth, 256); + sendStringToWs("errors", errorsHeapJson, num); + // если не было создано приема данных по udp - то создадим его + addThisDeviceToList(); + } + + // обработка кнопки сохранить настройки mqtt + if (headerStr == "/mqtt|") { + sendStringToWs("settin", settingsFlashJson, num); // отправляем в ответ новые полученные настройки + handleMqttStatus(false, 8); // меняем статус на неопределенный + mqttReconnect(); // начинаем переподключение + sendStringToWs("errors", errorsHeapJson, num); // отправляем что статус неопределен + sendStringToWs("ssidli", ssidListHeapJson, num); + } + + // запуск асинхронного сканирования wifi сетей при нажатии выпадающего списка + if (headerStr == "/scan|") + { + JsonArray jArray; + jsonReadArray(settingsFlashJson, "routerssid", jArray); + RouterFind(jArray); + sendStringToWs("ssidli", ssidListHeapJson, num); + } + + //----------------------------------------------------------------------// + // Страница веб интерфейса list + //----------------------------------------------------------------------// + + // отвечаем данными на запрос страницы list + if (headerStr == "/list|") { + sendStringToWs("settin", settingsFlashJson, num); + // отправим список устройств в зависимости от того что выбрал user + // sendDeviceList(num); + } + + // отвечаем на запрос списка устройств (это отдельный запрос который делает приложение при подключении) + if (headerStr == "/devlist|") { + // отправим список устройств в зависимости от того что выбрал user + sendDeviceList(num); + } + + // сохраняем данные листа + if (headerStr == "/tsil|") { + writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, 256); + } + + //----------------------------------------------------------------------// + // Страница веб интерфейса system + //----------------------------------------------------------------------// + + // отвечаем данными на запрос страницы + if (headerStr == "/system|") { + sendStringToWs("errors", errorsHeapJson, num); + sendStringToWs("settin", settingsFlashJson, 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 == "/test|") { + } + + //----------------------------------------------------------------------// + // отдельные команды веб интерфейса + //----------------------------------------------------------------------// + + // переписать любое поле в errors json + if (headerStr == "/rorre|") { + writeUint8tValueToJsonString(payload, length, headerLenth, errorsHeapJson); + } + + // команда перезагрузки esp + if (headerStr == "/reboot|") { + ESP.restart(); + } + + // команда очистки всех логов esp + if (headerStr == "/clean|") { + cleanLogs(); + } + + // команда обновления прошивки 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); + } + + if (headerStr == "/tst|") { + standWebSocket.sendTXT(num, "/tstr|"); + } + + // получаем команду посланную из модуля + if (headerStr == "/order|") { + String json; + writeUint8tToString(payload, length, headerLenth, json); + + String id, key, value; + jsonRead(json, "id", id); + jsonRead(json, "key", key); + jsonRead(json, "value", value); + + SerialPrint("i", F("=>WS"), "Msg from module, id: " + id); + + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + if ((*it)->getID() == id) { + (*it)->onModuleOrder(key, value); + } + } + } + + } 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_FRAGMENT_TEXT_START: { + Serial.printf("[%u] fragment test start: %u\n", num, length); + } break; + + case WStype_FRAGMENT_BIN_START: { + Serial.printf("[%u] fragment bin start: %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); +} + +// публикация дополнительных json сообщений в ws +void publishJsonWs(const String& topic, String& json) { + 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); + } +} + +#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); + } + Serial.printf("%02X ", *src); + src++; + } + 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]; + } + + 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) { + if (!(WiFi.softAPgetStationNum() || isNetworkActive())) { + return; + } + + if (header.length() != 6) { + SerialPrint("E", "FS", F("wrong header size")); + return; + } + + String msg = header + "|0012|" + payload; + size_t totalSize = msg.length(); + + char dataArray[totalSize]; + msg.toCharArray(dataArray, totalSize + 1); + if (client_id == -1) { + standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize); + } else { + standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize); + } +} + +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"); + } +} diff --git a/src/utils/JsonUtils.cpp b/src/utils/JsonUtils.cpp index 59950c9f..c07d99dd 100644 --- a/src/utils/JsonUtils.cpp +++ b/src/utils/JsonUtils.cpp @@ -1,320 +1,340 @@ -#include "utils/JsonUtils.h" -#include "utils/FileUtils.h" - -// new================================================================================ -String jsonReadStrDoc(DynamicJsonDocument& doc, String name) { - return doc[name].as(); -} - -void jsonWriteStrDoc(DynamicJsonDocument& doc, String name, String value) { - doc[name] = value; -} - -// new============================================================================== -bool jsonRead(const String& json, String key, long& value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - return false; - } else if (!doc.containsKey(key)) { - if (e) { - SerialPrint("E", F("jsonRead"), key + " missing in " + json); - jsonErrorDetected(); - } - return false; - } - value = doc[key].as(); - return true; -} - -bool jsonRead(const String& json, String key, float& value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - return false; - } else if (!doc.containsKey(key)) { - if (e) { - SerialPrint("E", F("jsonRead"), key + " missing in " + json); - jsonErrorDetected(); - } - return false; - } - value = doc[key].as(); - return true; -} - -bool jsonRead(const String& json, String key, String& value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - return false; - } else if (!doc.containsKey(key)) { - if (e) { - SerialPrint("E", F("jsonRead"), key + " missing in " + json); - jsonErrorDetected(); - } - return false; - } - value = doc[key].as(); - return true; -} - -bool jsonRead(const String& json, String key, bool& value, bool e) { - int lvalue = value; - bool ret = jsonRead(json, key, lvalue, e); - value = lvalue; - return ret; -} - -bool jsonRead(const String& json, String key, int& value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - return false; - } else if (!doc.containsKey(key)) { - if (e) { - SerialPrint("E", F("jsonRead"), key + " missing in " + json); - jsonErrorDetected(); - } - return false; - } - value = doc[key].as(); - return true; -} - -// new============================================================================== -bool jsonWriteStr_(String& json, const String& key, const String& value, bool e) { - bool ret = true; - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - ret = false; - } - doc[key] = value; - json = ""; - serializeJson(doc, json); - return ret; -} - -bool jsonWriteBool_(String& json, const String& key, bool value, bool e) { - bool ret = true; - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - ret = false; - } - doc[key] = value; - json = ""; - serializeJson(doc, json); - return ret; -} - -bool jsonWriteInt_(String& json, const String& key, int value, bool e) { - bool ret = true; - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - ret = false; - } - doc[key] = value; - json = ""; - serializeJson(doc, json); - return ret; -} - -bool jsonWriteFloat_(String& json, const String &key, float value, bool e) { - bool ret = true; - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - ret = false; - } - doc[key] = value; - json = ""; - serializeJson(doc, json); - return ret; -} - -void writeUint8tValueToJsonString(uint8_t* payload, size_t length, size_t headerLenth, String& json) { - String payloadStr; - payloadStr.reserve(length + 1); - for (size_t i = headerLenth; i < length; i++) { - payloadStr += (char)payload[i]; - } - jsonMergeObjects(json, payloadStr); -} - -bool jsonMergeObjects(String& json1, String& json2, bool e) { - bool ret = true; - DynamicJsonDocument doc1(JSON_BUFFER_SIZE); - DeserializationError error1 = deserializeJson(doc1, json1); - DynamicJsonDocument doc2(JSON_BUFFER_SIZE); - DeserializationError error2 = deserializeJson(doc2, json2); - jsonMergeDocs(doc1.as(), doc2.as()); - if (error1 || error2) { - if (e) { - SerialPrint("E", F("json"), "jsonMergeObjects error"); - jsonErrorDetected(); - } - ret = false; - } - json1 = ""; - serializeJson(doc1, json1); - return ret; -} - -void jsonMergeDocs(JsonObject dest, JsonObjectConst src) { - for (auto kvp : src) { - dest[kvp.key()] = kvp.value(); - } -} - -// depricated====================================================================== -String jsonReadStr(const String& json, String name, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - } - return doc[name].as(); -} - -boolean jsonReadBool(const String& json, String name, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - } - return doc[name].as(); -} - -int jsonReadInt(const String& json, String name, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - } - return doc[name].as(); -} - -long int jsonReadLInt(const String& json, String name, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonRead"), error.f_str()); - jsonErrorDetected(); - } - } - return doc[name].as(); -} - -// depricated======================================================================== -String jsonWriteStr(String& json, String name, String value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - } - doc[name] = value; - json = ""; - serializeJson(doc, json); - return json; -} - -String jsonWriteBool(String& json, String name, boolean value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - } - doc[name] = value; - json = ""; - serializeJson(doc, json); - return json; -} - -String jsonWriteInt(String& json, String name, int value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - } - doc[name] = value; - json = ""; - serializeJson(doc, json); - return json; -} - -String jsonWriteFloat(String& json, String name, float value, bool e) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, json); - if (error) { - if (e) { - SerialPrint("E", F("jsonWrite"), error.f_str()); - jsonErrorDetected(); - } - } - doc[name] = value; - json = ""; - serializeJson(doc, json); - return json; -} - -void jsonErrorDetected() { - // пример как отправить ошибку с количеством - // jsonWriteInt(errorsHeapJson, F("jse2"), 1); - // int number = jsonReadInt(errorsHeapJson, F("jse2n")); - // number++; - // jsonWriteInt(errorsHeapJson, F("jse2n"), number); +#include "utils/JsonUtils.h" +#include "utils/FileUtils.h" + +// new================================================================================ +String jsonReadStrDoc(DynamicJsonDocument& doc, String name) { + return doc[name].as(); +} + +void jsonWriteStrDoc(DynamicJsonDocument& doc, String name, String value) { + doc[name] = value; +} + +// new============================================================================== +bool jsonRead(const String& json, String key, long& value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + return false; + } else if (!doc.containsKey(key)) { + if (e) { + SerialPrint("E", F("jsonRead"), key + " missing in " + json); + jsonErrorDetected(); + } + return false; + } + value = doc[key].as(); + return true; +} + +bool jsonRead(const String& json, String key, float& value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + return false; + } else if (!doc.containsKey(key)) { + if (e) { + SerialPrint("E", F("jsonRead"), key + " missing in " + json); + jsonErrorDetected(); + } + return false; + } + value = doc[key].as(); + return true; +} + +bool jsonRead(const String& json, String key, String& value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + return false; + } else if (!doc.containsKey(key)) { + if (e) { + SerialPrint("E", F("jsonRead"), key + " missing in " + json); + jsonErrorDetected(); + } + return false; + } + value = doc[key].as(); + return true; +} + +bool jsonRead(const String& json, String key, bool& value, bool e) { + int lvalue = value; + bool ret = jsonRead(json, key, lvalue, e); + value = lvalue; + return ret; +} + +bool jsonRead(const String& json, String key, int& value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + return false; + } else if (!doc.containsKey(key)) { + if (e) { + SerialPrint("E", F("jsonRead"), key + " missing in " + json); + jsonErrorDetected(); + } + return false; + } + value = doc[key].as(); + return true; +} + +bool jsonReadArray(const String& json, String key, JsonArray& jArray, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonReadArray"), error.f_str()); + jsonErrorDetected(); + } + return false; + } else if (!doc.containsKey(key)) { + if (e) { + SerialPrint("E", F("jsonReadArray"), key + " missing in " + json); + jsonErrorDetected(); + } + return false; + } + jArray = doc[key]; + return true; +} + +// new============================================================================== +bool jsonWriteStr_(String& json, const String& key, const String& value, bool e) { + bool ret = true; + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + ret = false; + } + doc[key] = value; + json = ""; + serializeJson(doc, json); + return ret; +} + +bool jsonWriteBool_(String& json, const String& key, bool value, bool e) { + bool ret = true; + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + ret = false; + } + doc[key] = value; + json = ""; + serializeJson(doc, json); + return ret; +} + +bool jsonWriteInt_(String& json, const String& key, int value, bool e) { + bool ret = true; + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + ret = false; + } + doc[key] = value; + json = ""; + serializeJson(doc, json); + return ret; +} + +bool jsonWriteFloat_(String& json, const String &key, float value, bool e) { + bool ret = true; + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + ret = false; + } + doc[key] = value; + json = ""; + serializeJson(doc, json); + return ret; +} + +void writeUint8tValueToJsonString(uint8_t* payload, size_t length, size_t headerLenth, String& json) { + String payloadStr; + payloadStr.reserve(length + 1); + for (size_t i = headerLenth; i < length; i++) { + payloadStr += (char)payload[i]; + } + jsonMergeObjects(json, payloadStr); +} + +bool jsonMergeObjects(String& json1, String& json2, bool e) { + bool ret = true; + DynamicJsonDocument doc1(JSON_BUFFER_SIZE); + DeserializationError error1 = deserializeJson(doc1, json1); + DynamicJsonDocument doc2(JSON_BUFFER_SIZE); + DeserializationError error2 = deserializeJson(doc2, json2); + jsonMergeDocs(doc1.as(), doc2.as()); + if (error1 || error2) { + if (e) { + SerialPrint("E", F("json"), "jsonMergeObjects error"); + jsonErrorDetected(); + } + ret = false; + } + json1 = ""; + serializeJson(doc1, json1); + return ret; +} + +void jsonMergeDocs(JsonObject dest, JsonObjectConst src) { + for (auto kvp : src) { + dest[kvp.key()] = kvp.value(); + } +} + +// depricated====================================================================== +String jsonReadStr(const String& json, String name, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + } + return doc[name].as(); +} + +boolean jsonReadBool(const String& json, String name, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + } + return doc[name].as(); +} + +int jsonReadInt(const String& json, String name, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + } + return doc[name].as(); +} + +long int jsonReadLInt(const String& json, String name, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonRead"), error.f_str()); + jsonErrorDetected(); + } + } + return doc[name].as(); +} + +// depricated======================================================================== +String jsonWriteStr(String& json, String name, String value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + } + doc[name] = value; + json = ""; + serializeJson(doc, json); + return json; +} + +String jsonWriteBool(String& json, String name, boolean value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + } + doc[name] = value; + json = ""; + serializeJson(doc, json); + return json; +} + +String jsonWriteInt(String& json, String name, int value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + } + doc[name] = value; + json = ""; + serializeJson(doc, json); + return json; +} + +String jsonWriteFloat(String& json, String name, float value, bool e) { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, json); + if (error) { + if (e) { + SerialPrint("E", F("jsonWrite"), error.f_str()); + jsonErrorDetected(); + } + } + doc[name] = value; + json = ""; + serializeJson(doc, json); + return json; +} + +void jsonErrorDetected() { + // пример как отправить ошибку с количеством + // jsonWriteInt(errorsHeapJson, F("jse2"), 1); + // int number = jsonReadInt(errorsHeapJson, F("jse2n")); + // number++; + // jsonWriteInt(errorsHeapJson, F("jse2n"), number); } \ No newline at end of file diff --git a/src/utils/WiFiUtils.cpp b/src/utils/WiFiUtils.cpp index e5a10178..4da3f626 100644 --- a/src/utils/WiFiUtils.cpp +++ b/src/utils/WiFiUtils.cpp @@ -1,197 +1,210 @@ -#include "utils/WiFiUtils.h" -#include -#define TRIESONE 25 // количество попыток подключения к одной сети из несколких -#define TRIES 40 // количество попыток подключения сети если она одна - -void routerConnect() { - WiFi.setAutoConnect(false); - WiFi.persistent(false); - - WiFi.mode(WIFI_STA); - byte triesOne = TRIESONE; - - String _ssid = jsonReadStr(settingsFlashJson, "routerssid"); - String _password = jsonReadStr(settingsFlashJson, "routerpass"); - std::vector _ssidList; - std::vector _passwordList; - for (size_t i = 0; i < 3; i++) - { - String _stmp = selectFromMarkerToMarker(_ssid, ",", i); - String _ptmp = selectFromMarkerToMarker(_password, ",", i); - if (_stmp == "not found" && _ssidList.size() == 0) - { - triesOne = TRIES; - _ssidList.push_back(_ssid); - _passwordList.push_back(_password); - break; - } - if (_stmp != "not found") - { - _ssidList.push_back(_stmp); - _passwordList.push_back(_ptmp); - } - } - - if (_ssid == "" && _password == "") { - WiFi.begin(); - } else { - WiFi.begin(_ssidList[0].c_str(), _passwordList[0].c_str()); -#ifdef ESP32 - WiFi.setTxPower(WIFI_POWER_19_5dBm); -#else - WiFi.setOutputPower(20.5); -#endif - - if (_ssidList.size() > 1) - { - SerialPrint("i", "WIFI", "ssid list: " + _ssid); - SerialPrint("i", "WIFI", "pass list: " + _password); - } - } - for (size_t i = 0; i < _ssidList.size(); i++) { - triesOne = TRIESONE; - if (WiFi.status() == WL_CONNECTED) - break; - WiFi.begin(_ssidList[i].c_str(), _passwordList[i].c_str()); - SerialPrint("i", "WIFI", "ssid connect: " + _ssidList[i]); - SerialPrint("i", "WIFI", "pass connect: " + _passwordList[i]); - while (--triesOne && WiFi.status() != WL_CONNECTED) { -// SerialPrint("i", "WIFI", ": " + String((int)WiFi.status())); -#ifdef ESP8266 - if (WiFi.status() == WL_CONNECT_FAILED || WiFi.status() == WL_WRONG_PASSWORD) -#else - if (WiFi.status() == WL_CONNECT_FAILED) -#endif - { - SerialPrint("E", "WIFI", "password is not correct"); - triesOne = 1; - jsonWriteInt(errorsHeapJson, "passer", 1); - break; - } - Serial.print("."); - delay(1000); - } - Serial.println(""); - } - - if (WiFi.status() != WL_CONNECTED) { - Serial.println(""); - startAPMode(); - } else { - Serial.println(""); - SerialPrint("i", "WIFI", "http://" + WiFi.localIP().toString()); - jsonWriteStr(settingsFlashJson, "ip", WiFi.localIP().toString()); - - mqttInit(); - } - SerialPrint("i", F("WIFI"), F("Network Init")); -} - -bool startAPMode() { - SerialPrint("i", "WIFI", "AP Mode"); - - WiFi.disconnect(); - WiFi.mode(WIFI_AP); - - String _ssidAP = jsonReadStr(settingsFlashJson, "apssid"); - String _passwordAP = jsonReadStr(settingsFlashJson, "appass"); - - WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); - IPAddress myIP = WiFi.softAPIP(); - - SerialPrint("i", "WIFI", "AP IP: " + myIP.toString()); - jsonWriteStr(settingsFlashJson, "ip", myIP.toString()); - - if (jsonReadInt(errorsHeapJson, "passer") != 1) { - ts.add( - WIFI_SCAN, 30 * 1000, [&](void*) { - String sta_ssid = jsonReadStr(settingsFlashJson, "routerssid"); - - SerialPrint("i", "WIFI", "scanning for " + sta_ssid); - - if (RouterFind(sta_ssid)) { - ts.remove(WIFI_SCAN); - WiFi.scanDelete(); - routerConnect(); - } - }, - nullptr, true); - } - return true; -} - -boolean RouterFind(String ssid) { - bool res = false; - int n = WiFi.scanComplete(); - SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); - - if (n == -2) { //Сканирование не было запущено, запускаем - SerialPrint("i", "WIFI", "start scanning"); - WiFi.scanNetworks(true, false); // async, show_hidden - } - - else if (n == -1) { //Сканирование все еще выполняется - SerialPrint("i", "WIFI", "scanning in progress"); - } - - else if (n == 0) { //ни одна сеть не найдена - SerialPrint("i", "WIFI", "no networks found"); - WiFi.scanNetworks(true, false); - } - else if (n > 0) - { - std::vector _ssidList; - for (size_t i = 0; i < 3; i++) - { - String _stmp = selectFromMarkerToMarker(ssid, ",", i); - if (_stmp == "not found" && _ssidList.size() == 0) - { - _ssidList.push_back(ssid); - break; - } - if (_stmp != "not found") - _ssidList.push_back(_stmp); - } - - for (int8_t i = 0; i < n; i++) - { - if (WiFi.SSID(i) == _ssidList[0] || WiFi.SSID(i) == _ssidList[1] || - WiFi.SSID(i) == _ssidList[2]) - { - res = true; - } - // SerialPrint("i", "WIFI", (res ? "*" : "") + String(i, DEC) + ") " + WiFi.SSID(i)); - jsonWriteStr_(ssidListHeapJson, String(i), WiFi.SSID(i)); - - // String(WiFi.RSSI(i) - } - } - SerialPrint("i", "WIFI", ssidListHeapJson); - WiFi.scanDelete(); - return res; -} - -// boolean isNetworkActive() { -// return WiFi.status() == WL_CONNECTED; -// } - -uint8_t RSSIquality() { - uint8_t res = 0; - if (WiFi.status() == WL_CONNECTED) { - int rssi = WiFi.RSSI(); - if (rssi >= -50) { - res = 6; //"Excellent"; - } else if (rssi < -50 && rssi >= -60) { - res = 5; //"Very good"; - } else if (rssi < -60 && rssi >= -70) { - res = 4; //"Good"; - } else if (rssi < -70 && rssi >= -80) { - res = 3; //"Low"; - } else if (rssi < -80 && rssi > -100) { - res = 2; //"Very low"; - } else if (rssi <= -100) { - res = 1; //"No signal"; - } - } - return res; -} +#include "utils/WiFiUtils.h" +#include +#define TRIESONE 25 // количество попыток подключения к одной сети из несколких +#define TRIES 40 // количество попыток подключения сети если она одна + +void routerConnect() +{ + WiFi.setAutoConnect(false); + WiFi.persistent(false); + + WiFi.mode(WIFI_STA); + byte triesOne = TRIESONE; + + JsonArray _ssidList; + JsonArray _passwordList; + jsonReadArray(settingsFlashJson, "routerssid", _ssidList); + jsonReadStr(settingsFlashJson, "routerpass", _passwordList); + if (_ssidList.size() > 1) + triesOne = TRIES; + + if (_ssidList.size() == 0 && _ssidList[0] == "" && _passwordList[0] == "") + { + WiFi.begin(); + } + else + { + WiFi.begin(_ssidList[0].as(), _passwordList[0].as()); +#ifdef ESP32 + WiFi.setTxPower(WIFI_POWER_19_5dBm); +#else + WiFi.setOutputPower(20.5); +#endif + String _ssid; + String _password; + for (int8_t i = 0; i < _ssidList.size(); i++) + { + _ssid = _ssid + _ssidList[i].as() + "; "; + } + for (int8_t i = 0; i < _passwordList.size(); i++) + { + _password = _ssid + _passwordList[i].as() + "; "; + } + SerialPrint("i", "WIFI", "ssid list: " + _ssid); + SerialPrint("i", "WIFI", "pass list: " + _password); + } + for (size_t i = 0; i < _ssidList.size(); i++) + { + triesOne = TRIESONE; + if (WiFi.status() == WL_CONNECTED) + break; + WiFi.begin(_ssidList[i].as(), _passwordList[i].as()); + SerialPrint("i", "WIFI", "ssid connect: " + _ssidList[i].as()); + SerialPrint("i", "WIFI", "pass connect: " + _passwordList[i].as()); + while (--triesOne && WiFi.status() != WL_CONNECTED) + { +// SerialPrint("i", "WIFI", ": " + String((int)WiFi.status())); +#ifdef ESP8266 + if (WiFi.status() == WL_CONNECT_FAILED || WiFi.status() == WL_WRONG_PASSWORD) +#else + if (WiFi.status() == WL_CONNECT_FAILED) +#endif + { + SerialPrint("E", "WIFI", "password is not correct"); + triesOne = 1; + jsonWriteInt(errorsHeapJson, "passer", 1); + break; + } + Serial.print("."); + delay(1000); + } + Serial.println(""); + } + + if (WiFi.status() != WL_CONNECTED) + { + Serial.println(""); + startAPMode(); + } + else + { + Serial.println(""); + SerialPrint("i", "WIFI", "http://" + WiFi.localIP().toString()); + jsonWriteStr(settingsFlashJson, "ip", WiFi.localIP().toString()); + + mqttInit(); + } + SerialPrint("i", F("WIFI"), F("Network Init")); +} + +bool startAPMode() +{ + SerialPrint("i", "WIFI", "AP Mode"); + + WiFi.disconnect(); + WiFi.mode(WIFI_AP); + + String _ssidAP = jsonReadStr(settingsFlashJson, "apssid"); + String _passwordAP = jsonReadStr(settingsFlashJson, "appass"); + + WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); + IPAddress myIP = WiFi.softAPIP(); + + SerialPrint("i", "WIFI", "AP IP: " + myIP.toString()); + jsonWriteStr(settingsFlashJson, "ip", myIP.toString()); + + if (jsonReadInt(errorsHeapJson, "passer") != 1) + { + ts.add( + WIFI_SCAN, 30 * 1000, + [&](void *) + { + JsonArray jArray; + jsonReadArray(settingsFlashJson, "routerssid", jArray); + for (JsonVariant value : jArray) + { + SerialPrint("i", "WIFI", "scanning for " + String(value.as())); + } + if (RouterFind(jArray)) + { + ts.remove(WIFI_SCAN); + WiFi.scanDelete(); + routerConnect(); + } + }, + nullptr, true); + } + return true; +} + +boolean RouterFind(JsonArray jArray) +{ + bool res = false; + int n = WiFi.scanComplete(); + SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); + + if (n == -2) + { // Сканирование не было запущено, запускаем + SerialPrint("i", "WIFI", "start scanning"); + WiFi.scanNetworks(true, false); // async, show_hidden + } + + else if (n == -1) + { // Сканирование все еще выполняется + SerialPrint("i", "WIFI", "scanning in progress"); + } + + else if (n == 0) + { // ни одна сеть не найдена + SerialPrint("i", "WIFI", "no networks found"); + WiFi.scanNetworks(true, false); + } + else if (n > 0) + { + for (int8_t i = 0; i < n; i++) + { + for (int8_t k = 0; k < jArray.size(); k++) + { + if (WiFi.SSID(i) == String(jArray[k])) + { + res = true; + } + } + // SerialPrint("i", "WIFI", (res ? "*" : "") + String(i, DEC) + ") " + WiFi.SSID(i)); + jsonWriteStr_(ssidListHeapJson, String(i), WiFi.SSID(i)); + + // String(WiFi.RSSI(i) + } + } + SerialPrint("i", "WIFI", ssidListHeapJson); + WiFi.scanDelete(); + return res; +} + +// boolean isNetworkActive() { +// return WiFi.status() == WL_CONNECTED; +// } + +uint8_t RSSIquality() +{ + uint8_t res = 0; + if (WiFi.status() == WL_CONNECTED) + { + int rssi = WiFi.RSSI(); + if (rssi >= -50) + { + res = 6; //"Excellent"; + } + else if (rssi < -50 && rssi >= -60) + { + res = 5; //"Very good"; + } + else if (rssi < -60 && rssi >= -70) + { + res = 4; //"Good"; + } + else if (rssi < -70 && rssi >= -80) + { + res = 3; //"Low"; + } + else if (rssi < -80 && rssi > -100) + { + res = 2; //"Very low"; + } + else if (rssi <= -100) + { + res = 1; //"No signal"; + } + } + return res; +}