From 7d1c0268f5013626f81b2a2d149d473b8b1e522b Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 27 Mar 2020 15:48:17 +0100 Subject: [PATCH] Support logging of any sensor and charts --- Cmd.ino | 220 +++--------------- FS.ino | 38 +++ Init.ino | 59 ++--- Logging.ino | 145 ++++++++++++ SSDP.ino | 19 +- Scenario.ino | 4 +- Sensors.ino | 135 +++-------- Time.ino | 49 ++-- Timers.ino | 14 +- Upgrade.ino | 58 +++-- WiFi.ino | 22 +- Widgets.ino | 49 ++++ data/config.json | 2 +- data/configs/dht11.config.txt | 2 + data/js/function.js.gz | Bin 18057 -> 18140 bytes ...2-esp8266_iot-manager_modules_firmware.ino | 56 +---- main.ino | 55 +++-- mqtt.ino | 79 +++---- push_pushingbox.ino | 2 +- set.h | 20 +- test.ino | 55 +++++ 21 files changed, 579 insertions(+), 504 deletions(-) create mode 100644 FS.ino create mode 100644 Logging.ino create mode 100644 Widgets.ino create mode 100644 test.ino diff --git a/Cmd.ino b/Cmd.ino index d9bd1313..65285039 100644 --- a/Cmd.ino +++ b/Cmd.ino @@ -62,8 +62,8 @@ void button() { String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(optionJson, "button_param" + button_number, button_param); - jsonWrite(configJson, "buttonSet" + button_number, start_state); + jsonWriteStr(optionJson, "button_param" + button_number, button_param); + jsonWriteStr(configJson, "buttonSet" + button_number, start_state); if (isDigitStr (button_param)) { pinMode(button_param.toInt(), OUTPUT); @@ -71,7 +71,7 @@ void button() { } if (button_param == "scenario") { - jsonWrite(configSetup, "scenario", start_state); + jsonWriteStr(configSetup, "scenario", start_state); Scenario_init(); saveConfig(); } @@ -103,7 +103,7 @@ void buttonSet() { } if (button_param == "scenario") { - jsonWrite(configSetup, "scenario", button_state); + jsonWriteStr(configSetup, "scenario", button_state); Scenario_init(); saveConfig(); } @@ -124,7 +124,7 @@ void buttonSet() { eventGen ("buttonSet", button_number); - jsonWrite(configJson, "buttonSet" + button_number, button_state); + jsonWriteStr(configJson, "buttonSet" + button_number, button_state); sendSTATUS("buttonSet" + button_number, button_state); } @@ -137,7 +137,7 @@ void buttonChange() { current_state = "1"; } order_loop += "buttonSet " + button_number + " " + current_state + ","; - jsonWrite(configJson, "buttonSet" + button_number, current_state); + jsonWriteStr(configJson, "buttonSet" + button_number, current_state); sendSTATUS("buttonSet" + button_number, current_state); } @@ -168,11 +168,11 @@ void pwm() { uint8_t pwm_pin_int = pwm_pin.toInt(); - jsonWrite(optionJson, "pwm_pin" + pwm_number, pwm_pin); + jsonWriteStr(optionJson, "pwm_pin" + pwm_number, pwm_pin); pinMode(pwm_pin_int, INPUT); analogWrite(pwm_pin_int, start_state.toInt()); //analogWriteFreq(32000); - jsonWrite(configJson, "pwmSet" + pwm_number, start_state); + jsonWriteStr(configJson, "pwmSet" + pwm_number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.range.json", "pwmSet" + pwm_number); } @@ -188,7 +188,7 @@ void pwmSet() { eventGen ("pwmSet", pwm_number); - jsonWrite(configJson, "pwmSet" + pwm_number, pwm_state); + jsonWriteStr(configJson, "pwmSet" + pwm_number, pwm_state); sendSTATUS("pwmSet" + pwm_number, pwm_state); } //================================================================================================================== @@ -214,13 +214,13 @@ void handleButton() { eventGen ("switchSet", String(switch_number)); - jsonWrite(configJson, "switchSet" + String(switch_number), "1"); + jsonWriteStr(configJson, "switchSet" + String(switch_number), "1"); } if (buttons[switch_number].rose()) { eventGen ("switchSet", String(switch_number)); - jsonWrite(configJson, "switchSet" + String(switch_number), "0"); + jsonWriteStr(configJson, "switchSet" + String(switch_number), "0"); } } switch_number++; @@ -238,13 +238,13 @@ void inputDigit() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(configJson, "digitSet" + number, start_state); + jsonWriteStr(configJson, "digitSet" + number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digitSet" + number); } void digitSet() { String number = sCmd.next(); String value = sCmd.next(); - jsonWrite(configJson, "digitSet" + number, value); + jsonWriteStr(configJson, "digitSet" + number, value); sendSTATUS("digitSet" + number, value); } //===================================================================================================================================== @@ -258,13 +258,13 @@ void inputTime() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(configJson, "timeSet" + number, start_state); + jsonWriteStr(configJson, "timeSet" + number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.inputTime.json", "timeSet" + number); } void timeSet() { String number = sCmd.next(); String value = sCmd.next(); - jsonWrite(configJson, "timeSet" + number, value); + jsonWriteStr(configJson, "timeSet" + number, value); sendSTATUS("timeSet" + number, value); } @@ -273,7 +273,7 @@ void handle_time_init() { String tmp = GetTime(); tmp.replace(":", "-"); - jsonWrite(configJson, "timenowSet", tmp); + jsonWriteStr(configJson, "timenowSet", tmp); eventGen ("timenowSet", ""); }, nullptr, true); @@ -306,7 +306,7 @@ void textSet() { text = text + " " + GetDataDigital() + " " + time; } - jsonWrite(configJson, "textSet" + number, text); + jsonWriteStr(configJson, "textSet" + number, text); sendSTATUS("textSet" + number, text); } @@ -319,7 +319,7 @@ void stepper() { String pin_step = sCmd.next(); String pin_dir = sCmd.next(); - jsonWrite(optionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); + jsonWriteStr(optionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); pinMode(pin_step.toInt(), OUTPUT); pinMode(pin_dir.toInt(), OUTPUT); } @@ -328,7 +328,7 @@ void stepper() { void stepperSet() { String stepper_number = sCmd.next(); String steps = sCmd.next(); - jsonWrite(optionJson, "steps" + stepper_number, steps); + jsonWriteStr(optionJson, "steps" + stepper_number, steps); String stepper_speed = sCmd.next(); String pin_step = selectToMarker (jsonRead(optionJson, "stepper" + stepper_number), " "); String pin_dir = deleteBeforeDelimiter (jsonRead(optionJson, "stepper" + stepper_number), " "); @@ -377,13 +377,13 @@ void stepperSet() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(configJson, "inputTextSet" + number, start_state); + jsonWriteStr(configJson, "inputTextSet" + number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.inputText.json", "inputTextSet" + number); } void inputTextSet() { String number = sCmd.next(); String value = sCmd.next(); - jsonWrite(configJson, "inputTextSet" + number, value); + jsonWriteStr(configJson, "inputTextSet" + number, value); sendSTATUS("inputTextSet" + number, value); } @@ -395,14 +395,14 @@ void stepperSet() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(configJson, "inputTimeSet" + number, start_state); + jsonWriteStr(configJson, "inputTimeSet" + number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.inputTime.json", "inputTimeSet" + number); } void inputTimeSet() { String number = sCmd.next(); String value = sCmd.next(); value.replace(":", "."); - jsonWrite(configJson, "inputTimeSet" + number, value); + jsonWriteStr(configJson, "inputTimeSet" + number, value); value.replace(".", ":"); sendSTATUS("inputTimeSet" + number, value); } @@ -416,13 +416,13 @@ void stepperSet() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(configJson, "inputDateSet" + number, start_state); + jsonWriteStr(configJson, "inputDateSet" + number, start_state); createWidget (widget_name, page_name, page_number, "widgets/widget.inputDate.json", "inputDateSet" + number); } void inputDateSet() { String number = sCmd.next(); String value = sCmd.next(); - jsonWrite(configJson, "inputDateSet" + number, value); + jsonWriteStr(configJson, "inputDateSet" + number, value); sendSTATUS("inputDateSet" + number, value); } */ @@ -464,24 +464,6 @@ void handleCMD_loop() { } } -//=============================выполнение команд (через период) по очереди из строки order======================================= -/*void handleCMD_ticker() { - - ts.add(CMD, CMD_update_int, [&](void*) { - if (!busy) { - if (order_ticker != "") { - - String tmp = selectToMarker(order_ticker, ","); //выделяем из страки order первую команду pus title body - if (tmp != "no_command") sCmd.readStr(tmp); //выполняем первую команду - Serial.println("order_ticker => " + order_ticker); - order_ticker = deleteBeforeDelimiter(order_ticker, ","); //осекаем выполненную команду - } - } - }, nullptr, true); - }*/ - - - //======================================================================================================================================= //======================================================================================================================================= void txtExecution(String file) { @@ -497,6 +479,7 @@ void txtExecution(String file) { sCmd.readStr(tmp); command_all = deleteBeforeDelimiter(command_all, "\n"); } + command_all = ""; } void stringExecution(String str) { @@ -513,154 +496,3 @@ void stringExecution(String str) { str = deleteBeforeDelimiter(str, "\n"); } } - -//====================================================================================================================== -//===============================================Создание виджетов======================================================= - -void createWidget (String widget_name, String page_name, String page_number, String file, String topic) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - jsonWrite(widget, "page", page_name); - jsonWrite(widget, "order", page_number); - jsonWrite(widget, "descr", widget_name); - jsonWrite(widget, "topic", prex + "/" + topic); - all_widgets += widget + "\r\n"; - widget = ""; -} - -void createChart (String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - jsonWrite(widget, "page", page_name); - jsonWrite(widget, "order", page_number); - jsonWrite(widget, "descr", widget_name); - jsonWrite(widget, "series", widget_name); - jsonWrite(widget, "maxCount", maxCount); - jsonWrite(widget, "topic", prex + "/" + topic); - all_widgets += widget + "\r\n"; - widget = ""; -} - -/* - void createWidget (String widget_name, String page_name, String page_number, String file, String topic, String key, String value) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - value.replace("#", " "); - - widget = vidgetConfigWrite(widget, key, value); - - jsonWrite(widget, "page", page_name); - jsonWrite(widget, "pageId", page_number); - jsonWrite(widget, "descr", widget_name); - jsonWrite(widget, "topic", prex + "/" + topic); - - all_widgets += widget + "\r\n"; - widget = ""; - } - - void createWidget (String widget_name, String page_name, String page_number, String file, String topic, String key, String value, String key2, String value2) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - value.replace("#", " "); - - widget = vidgetConfigWrite(widget, key, value); - widget = vidgetConfigWrite(widget, key2, value2); - - jsonWrite(widget, "page", page_name); - jsonWrite(widget, "pageId", page_number); - jsonWrite(widget, "descr", widget_name); - jsonWrite(widget, "topic", prex + "/" + topic); - - all_widgets += widget + "\r\n"; - widget = ""; - } - -String vidgetConfigWrite(String widget, String key, String value) { - - if (widget == "") return ""; - if (widget == "{}") return ""; - int psn1 = widget.indexOf("{"); - if (psn1 != -1) { - psn1 = widget.indexOf("{", psn1 + 1); - if (psn1 != -1) { - int psn2 = widget.indexOf("}", psn1); - String WigetConfig = widget.substring(psn1, psn2) + "}"; - jsonWrite(WigetConfig, key, value); - String part1 = widget.substring(0, psn1); - widget = part1 + WigetConfig + "}"; - return widget; - - } - } -} -*/ - - - - - - - - - - - -//============разное - -/* - void delAlert() { - - String alert_id = sCmd.next(); - delwidget(alert_id); - sendAllWigets(); - } - - - void delwidget(String text_in_widget) { - String widget = all_widgets; - while (widget.length() != 0) { - String tmp = selectToMarkerPlus (widget, "\r\n", 2); - if (tmp.indexOf(text_in_widget) > 0) { - - all_widgets.replace(tmp, ""); - //Serial.println(all_widgets); - - widget = deleteBeforeDelimiter(widget, "\r\n"); - } else { - widget = deleteBeforeDelimiter(widget, "\r\n"); - } - } - } -*/ diff --git a/FS.ino b/FS.ino new file mode 100644 index 00000000..993c7dc8 --- /dev/null +++ b/FS.ino @@ -0,0 +1,38 @@ +void File_system_init() { + + Serial.begin(115200); + //Serial.setDebugOutput(true); + Serial.println("--------------started----------------"); + //-------------------------------------------------------------- + SPIFFS.begin(); + configSetup = readFile("config.json", 4096); + configSetup.replace(" ", ""); + configSetup.replace("\r\n", ""); + Serial.println(configSetup); + jsonWriteStr(configJson, "SSDP", jsonRead(configSetup, "SSDP")); + jsonWriteStr(configJson, "lang", jsonRead(configSetup, "lang")); + + +#ifdef ESP32 + uint32_t chipID_u = ESP.getEfuseMac(); + chipID = String(chipID_u); + jsonWriteStr(configSetup, "chipID", chipID); +#endif + +#ifdef ESP8266 + chipID = String( ESP.getChipId() ) + "-" + String(ESP.getFlashChipId()); + jsonWriteStr(configSetup, "chipID", chipID); + Serial.setDebugOutput(0); +#endif + + jsonWriteStr(configSetup, "firmware_version", firmware_version); + + prex = jsonRead(configSetup, "mqttPrefix") + "/" + chipID; + Serial.println(chipID); + +} + +void get_esp_info() { + + +} diff --git a/Init.ino b/Init.ino index bb36f33c..423a711e 100644 --- a/Init.ino +++ b/Init.ino @@ -7,7 +7,7 @@ void All_init() { server.on("/scenario", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("status")) { - jsonWrite(configSetup, "scenario", request->getParam("status")->value()); + jsonWriteStr(configSetup, "scenario", request->getParam("status")->value()); } saveConfig(); Scenario_init(); @@ -15,11 +15,9 @@ void All_init() { }); server.on("/cleanlog", HTTP_GET, [](AsyncWebServerRequest * request) { - SPIFFS.remove("/log.analog.txt"); - SPIFFS.remove("/log.dallas.txt"); - SPIFFS.remove("/log.level.txt"); - SPIFFS.remove("/log.ph.txt"); - SPIFFS.remove("/log.txt"); + + clean_log_date(); + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); @@ -43,7 +41,12 @@ void Device_init() { ts.remove(STEPPER1); ts.remove(STEPPER2); + #ifdef layout_in_rom all_widgets = ""; + #else + SPIFFS.remove("/layout.txt"); + #endif + txtExecution("firmware.config.txt"); //outcoming_date(); } @@ -219,19 +222,19 @@ void up_time() { if (ss != 0) { out = "[i] uptime = " + String(ss) + " sec"; - jsonWrite(configJson, "uptime", String(ss) + " sec"); + jsonWriteStr(configJson, "uptime", String(ss) + " sec"); } if (mm != 0) { out = "[i] uptime = " + String(mm) + " min"; - jsonWrite(configJson, "uptime", String(mm) + " min"); + jsonWriteStr(configJson, "uptime", String(mm) + " min"); } if (hh != 0) { out = "[i] uptime = " + String(hh) + " hours"; - jsonWrite(configJson, "uptime", String(hh) + " hours"); + jsonWriteStr(configJson, "uptime", String(hh) + " hours"); } if (dd != 0) { out = "[i] uptime = " + String(dd) + " days"; - jsonWrite(configJson, "uptime", String(dd) + " days"); + jsonWriteStr(configJson, "uptime", String(dd) + " days"); } Serial.println(out + ", mqtt_lost_error: " + String(mqtt_lost_error) + ", wifi_lost_error: " + String(wifi_lost_error)); } @@ -245,29 +248,31 @@ void statistics_init() { } void statistics() { - String urls = "http://backup.privet.lv/visitors/?"; - //----------------------------------------------------------------- - urls += WiFi.macAddress().c_str(); - urls += "&"; - //----------------------------------------------------------------- + if (WiFi.status() == WL_CONNECTED) { + String urls = "http://backup.privet.lv/visitors/?"; + //----------------------------------------------------------------- + urls += WiFi.macAddress().c_str(); + urls += "&"; + //----------------------------------------------------------------- #ifdef ESP8266 - urls += "iot-manager_esp8266"; + urls += "iot-manager_esp8266"; #endif #ifdef ESP32 - urls += "iot-manager_esp32"; + urls += "iot-manager_esp32"; #endif - urls += "&"; - //----------------------------------------------------------------- + urls += "&"; + //----------------------------------------------------------------- #ifdef ESP8266 - urls += ESP.getResetReason(); + urls += ESP.getResetReason(); #endif #ifdef ESP32 - urls += "Unknown"; + urls += "Unknown"; #endif - urls += "&"; - //----------------------------------------------------------------- - urls += "firm version: " + firmware_version + " " + DATE_COMPILING + " " + TIME_COMPILING; - //----------------------------------------------------------------- - String stat = getURL(urls); - //Serial.println(stat); + urls += "&"; + //----------------------------------------------------------------- + urls += "firm version: " + firmware_version + " " + DATE_COMPILING + " " + TIME_COMPILING; + //----------------------------------------------------------------- + String stat = getURL(urls); + //Serial.println(stat); + } } diff --git a/Logging.ino b/Logging.ino new file mode 100644 index 00000000..423062bb --- /dev/null +++ b/Logging.ino @@ -0,0 +1,145 @@ +//===============================================Логирование============================================================ +void logging() { + + static boolean flag = true; + + String sensor_name = sCmd.next(); + String period_min = sCmd.next(); + String maxCount = sCmd.next(); + + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + + if (sensor_name == "analog") jsonWriteStr(optionJson, "analog_logging_count", maxCount); + if (sensor_name == "level") jsonWriteStr(optionJson, "level_logging_count", maxCount); + if (sensor_name == "dallas") jsonWriteStr(optionJson, "dallas_logging_count", maxCount); + if (sensor_name == "dhtT") jsonWriteStr(optionJson, "dhtT_logging_count", maxCount); + if (sensor_name == "dhtH") jsonWriteStr(optionJson, "dhtH_logging_count", maxCount); + + if (sensor_name == "analog") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "loganalog", maxCount); + if (sensor_name == "level") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "loglevel", maxCount); + if (sensor_name == "dallas") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "logdallas", maxCount); + if (sensor_name == "dhtT") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "logdhtT", maxCount); + if (sensor_name == "dhtH") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "logdhtH", maxCount); + + if (sensor_name == "analog") { + flagLoggingAnalog = true; + ts.remove(ANALOG_LOG); + ts.add(ANALOG_LOG, period_min.toInt() * 1000 * 60, [&](void*) { + deleteOldDate("log.analog.txt", jsonReadtoInt(optionJson, "analog_logging_count"), jsonRead(configJson, "analog")); + }, nullptr, true); + } + + if (sensor_name == "level") { + flagLoggingLevel = true; + ts.remove(LEVEL_LOG); + ts.add(LEVEL_LOG, period_min.toInt() * 1000 * 60, [&](void*) { + deleteOldDate("log.level.txt", jsonReadtoInt(optionJson, "level_logging_count"), jsonRead(configJson, "level")); + }, nullptr, true); + } + + if (sensor_name == "dallas") { + flagLoggingDallas = true; + ts.remove(DALLAS_LOG); + ts.add(DALLAS_LOG, period_min.toInt() * 1000 * 60, [&](void*) { + deleteOldDate("log.dallas.txt", jsonReadtoInt(optionJson, "dallas_logging_count"), jsonRead(configJson, "dallas")); + }, nullptr, true); + } + + if (sensor_name == "dhtT") { + flagLoggingdhtT = true; + ts.remove(dhtT_LOG); + ts.add(dhtT_LOG, period_min.toInt() * 1000 * 60, [&](void*) { + deleteOldDate("log.dhtT.txt", jsonReadtoInt(optionJson, "dhtT_logging_count"), jsonRead(configJson, "dhtT")); + }, nullptr, true); + } + + if (sensor_name == "dhtH") { + flagLoggingdhtH = true; + ts.remove(dhtH_LOG); + ts.add(dhtH_LOG, period_min.toInt() * 1000 * 60, [&](void*) { + deleteOldDate("log.dhtH.txt", jsonReadtoInt(optionJson, "dhtH_logging_count"), jsonRead(configJson, "dhtH")); + }, nullptr, true); + } +} + +//=========================================Удаление стрых данных и запись новых================================================================== +void deleteOldDate(String file, int seted_number_of_lines, String date_to_add) { + String log_date = readFile(file, 5000); + int current_number_of_lines = count(log_date, "\n"); + Serial.println("=====> [i] in log file " + file + " " + current_number_of_lines + " lines"); + + if (current_number_of_lines > seted_number_of_lines + 1) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines == 0) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines > seted_number_of_lines) { + log_date = deleteBeforeDelimiter(log_date, "\n"); + if (GetTimeUnix() != "failed") { + log_date += GetTimeUnix() + " " + date_to_add + "\n"; + writeFile(file, log_date); + } + } else { + if (GetTimeUnix() != "failed") { + addFile(file, GetTimeUnix() + " " + date_to_add); + } + } + log_date = ""; +} + +//=========================================Выбор какие данные отправлять================================================================== +void choose_log_date_and_send() { + if (flagLoggingAnalog) sendLogData("log.analog.txt", "loganalog"); + if (flagLoggingLevel) sendLogData("log.level.txt", "loglevel"); + if (flagLoggingDallas) sendLogData("log.dallas.txt", "logdallas"); + if (flagLoggingdhtT) sendLogData("log.dhtT.txt", "logdhtT"); + if (flagLoggingdhtH) sendLogData("log.dhtH.txt", "logdhtH"); +} + +//=========================================Отправка данных=================================================================================== +void sendLogData(String file, String topic) { + String log_date = readFile(file, 5000); + log_date.replace("\r\n", "\n"); + log_date.replace("\r", "\n"); + String buf = "{}"; + String json_array; + String unix_time; + String value; + while (log_date.length() != 0) { + String tmp = selectToMarker (log_date, "\n"); + log_date = deleteBeforeDelimiter(log_date, "\n"); + unix_time = selectToMarker (tmp, " "); + jsonWriteInt(buf, "x", unix_time.toInt()); + value = deleteBeforeDelimiter(tmp, " "); + jsonWriteFloat(buf, "y1", value.toFloat()); + if (log_date.length() < 3) { + json_array += buf; + } else { + json_array += buf + ","; + } + buf = "{}"; + } + unix_time = ""; + value = ""; + log_date = ""; + json_array = "{\"status\":[" + json_array + "]}"; + Serial.println(json_array); + sendCHART(topic, json_array); + json_array = ""; + getMemoryLoad("[i] after send log date"); +} + +//=========================================Очистка данных=================================================================================== +void clean_log_date() { + SPIFFS.remove("/log.analog.txt"); + SPIFFS.remove("/log.level.txt"); + SPIFFS.remove("/log.dallas.txt"); + SPIFFS.remove("/log.dhtT.txt"); + SPIFFS.remove("/log.dhtH.txt"); +} diff --git a/SSDP.ino b/SSDP.ino index 2ee42981..2638e15a 100644 --- a/SSDP.ino +++ b/SSDP.ino @@ -1,11 +1,20 @@ -/* void SSDP_init() { + server.on("/ssdp", HTTP_GET, [](AsyncWebServerRequest * request) { + if (request->hasArg("ssdp")) { + jsonWriteStr(configSetup, "SSDP", request->getParam("ssdp")->value()); + jsonWriteStr(configJson, "SSDP", request->getParam("ssdp")->value()); + } + saveConfig(); + request->send(200, "text/text", "OK"); + }); +} +/* // --------------------Получаем ssdp со страницы server.on("/ssdp", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("ssdp")) { - jsonWrite(configSetup, "SSDP", request->getParam("ssdp")->value()); - jsonWrite(configJson, "SSDP", request->getParam("ssdp")->value()); + jsonWriteStr(configSetup, "SSDP", request->getParam("ssdp")->value()); + jsonWriteStr(configJson, "SSDP", request->getParam("ssdp")->value()); SSDP.setName(jsonRead(configSetup, "SSDP")); } saveConfig(); @@ -13,7 +22,7 @@ void SSDP_init() { }); // SSDP дескриптор - server.on("/description.xml", [](AsyncWebServerRequest * request) { + server.on("/description.xml", [](AsyncWebServerRequest * request) { //SSDP.schema(http.client()); request->send(200, "text/text", "OK"); }); @@ -36,5 +45,5 @@ void SSDP_init() { SSDP.setManufacturerURL("https://www.instagram.com/rriissee3"); SSDP.begin(); } -} + } */ diff --git a/Scenario.ino b/Scenario.ino index d4c17a98..67b422f4 100644 --- a/Scenario.ino +++ b/Scenario.ino @@ -69,7 +69,7 @@ void handleScenario() { } String tmp2 = jsonRead(optionJson, "scenario_status"); //читаем файл событий tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие - jsonWrite(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий + jsonWriteStr(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий i = 0; } } @@ -80,7 +80,7 @@ void eventGen (String event_name, String number) { //событие выгля if (jsonRead(configSetup, "scenario") == "1") { String tmp = jsonRead(optionJson, "scenario_status") ; //генерирование события //Serial.println(event_name); - jsonWrite(optionJson, "scenario_status", tmp + event_name + number + ","); + jsonWriteStr(optionJson, "scenario_status", tmp + event_name + number + ","); } } diff --git a/Sensors.ino b/Sensors.ino index 3c1986f0..a1da758c 100644 --- a/Sensors.ino +++ b/Sensors.ino @@ -10,10 +10,10 @@ void analog() { String analog_start_out = sCmd.next(); String analog_end_out = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(optionJson, "analog_start", analog_start); - jsonWrite(optionJson, "analog_end", analog_end); - jsonWrite(optionJson, "analog_start_out", analog_start_out); - jsonWrite(optionJson, "analog_end_out", analog_end_out); + jsonWriteStr(optionJson, "analog_start", analog_start); + jsonWriteStr(optionJson, "analog_end", analog_end); + jsonWriteStr(optionJson, "analog_start_out", analog_start_out); + jsonWriteStr(optionJson, "analog_end_out", analog_end_out); choose_widget_and_create(widget_name, page_name, page_number, type, "analog"); ts.add(ANALOG_, analog_update_int, [&](void*) { static int analog_old; @@ -24,13 +24,13 @@ void analog() { #ifdef ESP8266 int analog_in = analogRead(A0); #endif - jsonWrite(configJson, "analog_in", analog_in); + jsonWriteInt(configJson, "analog_in", analog_in); int analog = map(analog_in, jsonReadtoInt(optionJson, "analog_start") , jsonReadtoInt(optionJson, "analog_end"), jsonReadtoInt(optionJson, "analog_start_out"), jsonReadtoInt(optionJson, "analog_end_out")); - jsonWrite(configJson, "analog", analog); + jsonWriteInt(configJson, "analog", analog); // if (analog_old != analog) { eventGen ("analog", ""); sendSTATUS("analog", String(analog)); @@ -51,8 +51,8 @@ void level() { String empty_level = sCmd.next(); String full_level = sCmd.next(); String page_number = sCmd.next(); - jsonWrite(optionJson, "empty_level", empty_level); - jsonWrite(optionJson, "full_level", full_level); + jsonWriteStr(optionJson, "empty_level", empty_level); + jsonWriteStr(optionJson, "full_level", full_level); pinMode(14, OUTPUT); pinMode(12, INPUT); choose_widget_and_create(widget_name, page_name, page_number, type, "level"); @@ -73,11 +73,11 @@ void level() { counter++; if (counter > tank_level_times_to_send) { counter = 0; - jsonWrite(configJson, "level_in", distance_cm); + jsonWriteInt(configJson, "level_in", distance_cm); level = map(distance_cm, jsonReadtoInt(optionJson, "empty_level"), jsonReadtoInt(optionJson, "full_level"), 0, 100); - jsonWrite(configJson, "level", level); + jsonWriteInt(configJson, "level", level); //if (level_old != level) { eventGen ("level", ""); sendSTATUS("level", String(level)); @@ -108,7 +108,7 @@ void dallas() { static float temp_old; sensors.requestTemperatures(); temp = sensors.getTempCByIndex(0); - jsonWrite(configJson, "dallas", String(temp)); + jsonWriteStr(configJson, "dallas", String(temp)); //if (temp_old != temp) { eventGen ("dallas", ""); sendSTATUS("dallas", String(temp)); @@ -147,14 +147,16 @@ void dhtT() { } else { counter = 0; value = dht.getTemperature(); - jsonWrite(configJson, "dhtT", String(value)); //if (value_old != value) { - eventGen ("dhtT", ""); - sendSTATUS("dhtT", String(value)); - if (client.connected()) { - Serial.println("[i] sensor 'dhtT' send date " + String(value)); + if (String(value) != "nan") { + eventGen ("dhtT", ""); + jsonWriteStr(configJson, "dhtT", String(value)); + sendSTATUS("dhtT", String(value)); + if (client.connected()) { + Serial.println("[i] sensor 'dhtT' send date " + String(value)); + } + //} } - //} value_old = value; } }, nullptr, true); @@ -185,14 +187,16 @@ void dhtH() { } else { counter = 0; value = dht.getHumidity(); - jsonWrite(configJson, "dhtH", String(value)); - //if (value_old != value) { - eventGen ("dhtH", ""); - sendSTATUS("dhtH", String(value)); - if (client.connected()) { - Serial.println("[i] sensor 'dhtH' send date " + String(value)); + if (String(value) != "nan") { + //if (value_old != value) { + eventGen ("dhtH", ""); + jsonWriteStr(configJson, "dhtH", String(value)); + sendSTATUS("dhtH", String(value)); + if (client.connected()) { + Serial.println("[i] sensor 'dhtH' send date " + String(value)); + } + //} } - //} value_old = value; } }, nullptr, true); @@ -210,7 +214,7 @@ void dhtPerception() { } else { value = dht.computePerception(jsonRead(configJson, "dhtT").toFloat(), jsonRead(configJson, "dhtH").toFloat(), false); String final_line = perception(value); - jsonWrite(configJson, "dhtPerception", final_line); + jsonWriteStr(configJson, "dhtPerception", final_line); eventGen ("dhtPerception", ""); sendSTATUS("dhtPerception", final_line); if (client.connected()) { @@ -277,7 +281,7 @@ void dhtComfort() { break; }; String final_line = comfortStatus; - jsonWrite(configJson, "dhtComfort", final_line); + jsonWriteStr(configJson, "dhtComfort", final_line); eventGen ("dhtComfort", ""); sendSTATUS("dhtComfort", final_line); if (client.connected()) { @@ -298,7 +302,7 @@ void dhtDewpoint() { sendSTATUS("dhtDewpoint", String(dht.getStatusString())); } else { value = dht.computeDewPoint(jsonRead(configJson, "dhtT").toFloat(), jsonRead(configJson, "dhtH").toFloat(), false); - jsonWrite(configJson, "dhtDewpoint", value); + jsonWriteInt(configJson, "dhtDewpoint", value); eventGen ("dhtDewpoint", ""); sendSTATUS("dhtDewpoint", String(value)); if (client.connected()) { @@ -317,80 +321,3 @@ void choose_widget_and_create(String widget_name, String page_name, String page_ if (type == "fill-gauge") createWidget (widget_name, page_name, page_number, "widgets/widget.fillGauge.json", topik); } -//====================================================================================================================== -//===============================================Логирование============================================================ - -void logging() { - - static boolean flag = true; - - String sensor_name = sCmd.next(); - String period_min = sCmd.next(); - String maxCount = sCmd.next(); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - - if (sensor_name == "analog") jsonWrite(optionJson, "analog_logging_count", maxCount); - if (sensor_name == "level") jsonWrite(optionJson, "level_logging_count", maxCount); - if (sensor_name == "dallas") jsonWrite(optionJson, "dallas_logging_count", maxCount); - - if (sensor_name == "analog") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "loganalog", maxCount); - if (sensor_name == "level") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "loglevel", maxCount); - if (sensor_name == "dallas") createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", "logdallas", maxCount); - - if (sensor_name == "analog") { - flagLoggingAnalog = true; - ts.remove(ANALOG_LOG); - ts.add(ANALOG_LOG, period_min.toInt() * 1000 * 60, [&](void*) { - deleteOldDate("log.analog.txt", jsonReadtoInt(optionJson, "analog_logging_count"), jsonRead(configJson, "analog")); - }, nullptr, true); - } - - if (sensor_name == "level") { - flagLoggingLevel = true; - ts.remove(LEVEL_LOG); - ts.add(LEVEL_LOG, period_min.toInt() * 1000 * 60, [&](void*) { - deleteOldDate("log.level.txt", jsonReadtoInt(optionJson, "level_logging_count"), jsonRead(configJson, "level")); - }, nullptr, true); - } - - if (sensor_name == "dallas") { - flagLoggingDallas = true; - ts.remove(DALLAS_LOG); - ts.add(DALLAS_LOG, period_min.toInt() * 1000 * 60, [&](void*) { - deleteOldDate("log.dallas.txt", jsonReadtoInt(optionJson, "dallas_logging_count"), jsonRead(configJson, "dallas")); - }, nullptr, true); - } -} - -void deleteOldDate(String file, int seted_number_of_lines, String date_to_add) { - - String log_date = readFile(file, 5000); - - //getMemoryLoad("[i] after logging procedure"); - //предел количества строк 255 - - log_date.replace("\r\n", "\n"); - log_date.replace("\r", "\n"); - - int current_number_of_lines = count(log_date, "\n"); - Serial.println("[i] in log file " + file + " " + current_number_of_lines + " lines"); - - if (current_number_of_lines > seted_number_of_lines + 1) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; - } - if (current_number_of_lines == 0) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; - } - if (current_number_of_lines > seted_number_of_lines) { - log_date = deleteBeforeDelimiter(log_date, "\n"); - log_date += String(GetTimeUnix()) + " " + date_to_add + "\n"; - writeFile(file, log_date); - } else { - addFile(file, String(GetTimeUnix()) + " " + date_to_add); - } -} diff --git a/Time.ino b/Time.ino index 792ade44..28880429 100644 --- a/Time.ino +++ b/Time.ino @@ -1,23 +1,26 @@ void Time_Init() { server.on("/timeZone", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("timezone")) { - jsonWrite(configSetup, "timezone", request->getParam("timezone")->value()); + jsonWriteStr(configSetup, "timezone", request->getParam("timezone")->value()); } saveConfig(); reconfigTime(); request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); - reconfigTime(); + + ts.add(TIME_SYNC, 30000, [&](void*) { + if (GetTimeUnix() == "failed") { + Serial.println("[i] Time is not synchronized, start synchronization"); + reconfigTime(); + } + }, nullptr, true); } void reconfigTime() { if (WiFi.status() == WL_CONNECTED) { - - configTime(jsonRead(configSetup, "timezone").toInt() * 3600, 0, ntpServer); - + configTime(0, 0, ntpServer); int i = 0; Serial.println("[i] Awaiting for time "); - #ifdef ESP32 struct tm timeinfo; while (!getLocalTime(&timeinfo) && i <= 4) { @@ -26,7 +29,6 @@ void reconfigTime() { delay(1000); } #endif - #ifdef ESP8266 // while (!time(nullptr) && i < 4) { // Serial.print("."); @@ -34,26 +36,33 @@ void reconfigTime() { delay(2000); // } #endif - - Serial.print("[i] Time = "); - Serial.print(GetDataDigital()); - Serial.print(" "); - Serial.println(GetTime()); - - - + if (GetTimeUnix() != "failed") { + Serial.print("[V] Time synchronized = "); + Serial.print(GetDataDigital()); + Serial.print(" "); + Serial.println(GetTime()); + } else { + Serial.println("[E] Time server or internet connection error, will try again in 30 sec"); + } } else { Serial.println("[E] Get time impossible, no wifi connection"); } } -//Получаем время в формате linux -int GetTimeUnix() { + +//Получаем время в формате linux gmt +String GetTimeUnix() { time_t now = time(nullptr); - return (now); + if (now < 30000) { + return "failed"; + } else { + return String(now); + } } // Получение текущего времени String GetTime() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonRead(configSetup, "timezone").toInt(); + now = now + zone; String Time = ""; // Строка для результатов времени Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 int i = Time.indexOf(":"); //Ишем позицию первого символа : @@ -63,6 +72,8 @@ String GetTime() { String GetTimeWOsec() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonRead(configSetup, "timezone").toInt(); + now = now + zone; String Time = ""; // Строка для результатов времени Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 int i = Time.indexOf(":"); //Ишем позицию первого символа : @@ -73,6 +84,8 @@ String GetTimeWOsec() { // Получение даты String GetDate() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonRead(configSetup, "timezone").toInt(); + now = now + zone; String Data = ""; // Строка для результатов времени Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 Data.replace("\n", ""); diff --git a/Timers.ino b/Timers.ino index e6bfa22c..ea86117c 100644 --- a/Timers.ino +++ b/Timers.ino @@ -25,7 +25,7 @@ void Timer_countdown_init() { delTimer (String (number)); - jsonWrite(configJson, "timerSet" + String(number), "0"); + jsonWriteStr(configJson, "timerSet" + String(number), "0"); eventGen ("timerSet", String(number)); @@ -58,7 +58,7 @@ void timerStart() { if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); addTimer(number, period_of_time); - jsonWrite(configJson, "timerSet" + number, "1"); + jsonWriteStr(configJson, "timerSet" + number, "1"); } void addTimer(String number, String time) { @@ -78,7 +78,7 @@ void addTimer(String number, String time) { } else { //если его нет tmp += new_timer + ","; } - jsonWrite(optionJson, "timers", tmp); + jsonWriteStr(optionJson, "timers", tmp); //Serial.println("ura"); } @@ -98,7 +98,7 @@ void delTimer (String number) { int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить tmp.replace(timer, ""); //удаляем таймер - jsonWrite(optionJson, "timers", tmp); + jsonWriteStr(optionJson, "timers", tmp); } } @@ -157,9 +157,9 @@ void time() { } - jsonWrite(optionJson, "times", replace_line); + jsonWriteStr(optionJson, "times", replace_line); - jsonWrite(configJson, "timeSet" + time_number, "1"); + jsonWriteStr(configJson, "timeSet" + time_number, "1"); ts.add(TIMERS, 1000, [&](void*) { @@ -177,7 +177,7 @@ void time() { Serial.println(seted_time); if (current_time == seted_time) { - jsonWrite(configJson, "timeSet" + time_number, "0"); + jsonWriteStr(configJson, "timeSet" + time_number, "0"); eventGen ("timeSet", time_number); } diff --git a/Upgrade.ino b/Upgrade.ino index c366966e..f8b19d1b 100644 --- a/Upgrade.ino +++ b/Upgrade.ino @@ -1,39 +1,55 @@ void initUpgrade() { + +#ifdef ESP8266 + if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); +#endif +#ifdef ESP32 + if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); +#endif + jsonWriteStr(configSetup, "last_version", last_version); + Serial.print("[i] Last firmware version: "); + Serial.println(last_version); + server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest * request) { start_check_version = true; Serial.print("[i] Last firmware version: "); Serial.println(last_version); - +#ifdef ESP8266 + int ChipRealSize = ESP.getFlashChipRealSize() / 1048576; +#endif +#ifdef ESP32 + int ChipRealSize = 4; +#endif String tmp = "{}"; if (WiFi.status() == WL_CONNECTED) { - if (!flash_1mb) { + if (ChipRealSize >= 4) { if (last_version != "") { if (last_version != "error") { if (last_version == firmware_version) { - jsonWrite(tmp, "title", "Последняя версия прошивки уже установлена."); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Последняя версия прошивки уже установлена."); + jsonWriteStr(tmp, "class", "pop-up"); } else { upgrade_flag = true; - jsonWrite(tmp, "title", "Идет обновление прошивки... После завершения устройство перезагрузится. Подождите одну минуту!!!"); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Идет обновление прошивки... После завершения устройство перезагрузится. Подождите одну минуту!!!"); + jsonWriteStr(tmp, "class", "pop-up"); } } else { - jsonWrite(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); + jsonWriteStr(tmp, "class", "pop-up"); } } else { - jsonWrite(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); + jsonWriteStr(tmp, "class", "pop-up"); } } else { - jsonWrite(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); + jsonWriteStr(tmp, "class", "pop-up"); } } else { - jsonWrite(tmp, "title", "Модуль не подключен к роутеру..."); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "Устройство не подключен к роутеру..."); + jsonWriteStr(tmp, "class", "pop-up"); } request->send(200, "text/text", tmp); }); @@ -44,9 +60,11 @@ void handle_get_url() { start_check_version = false; #ifdef ESP32 last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); + jsonWriteStr(configSetup, "last_version", last_version); #endif #ifdef ESP8266 last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); + jsonWriteStr(configSetup, "last_version", last_version); #endif } } @@ -232,24 +250,24 @@ void handle_upgrade() { case HTTP_UPDATE_FAILED: Serial.println(mode + "_FAILED"); var = "{}"; - jsonWrite(var, "title", "_FAILED"); - jsonWrite(var, "class", "pop-up"); + jsonWriteStr(var, "title", "_FAILED"); + jsonWriteStr(var, "class", "pop-up"); //request->send(200, "text/text", var); break; case HTTP_UPDATE_NO_UPDATES: Serial.println(mode + "_NO_UPDATES"); var = "{}"; - jsonWrite(var, "title", "_NO_UPDATES"); - jsonWrite(var, "class", "pop-up"); + jsonWriteStr(var, "title", "_NO_UPDATES"); + jsonWriteStr(var, "class", "pop-up"); //request->send(200, "text/text", var); break; case HTTP_UPDATE_OK: Serial.println(mode + "_UPDATE_OK"); var = "{}"; - jsonWrite(var, "title", "_UPDATE_OK"); - jsonWrite(var, "class", "pop-up"); + jsonWriteStr(var, "title", "_UPDATE_OK"); + jsonWriteStr(var, "class", "pop-up"); //request->send(200, "text/text", var); break; } diff --git a/WiFi.ino b/WiFi.ino index 086834d1..20f9f44c 100644 --- a/WiFi.ino +++ b/WiFi.ino @@ -3,10 +3,10 @@ void WIFI_init() { // --------------------Получаем ssid password со страницы server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("ssid")) { - jsonWrite(configSetup, "ssid", request->getParam("ssid")->value()); + jsonWriteStr(configSetup, "ssid", request->getParam("ssid")->value()); } if (request->hasArg("password")) { - jsonWrite(configSetup, "password", request->getParam("password")->value()); + jsonWriteStr(configSetup, "password", request->getParam("password")->value()); } saveConfig(); // Функция сохранения данных во Flash request->send(200, "text/text", "OK"); // отправляем ответ о выполнении @@ -14,10 +14,10 @@ void WIFI_init() { // --------------------Получаем ssidAP passwordAP со страницы server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("ssidAP")) { - jsonWrite(configSetup, "ssidAP", request->getParam("ssidAP")->value()); + jsonWriteStr(configSetup, "ssidAP", request->getParam("ssidAP")->value()); } if (request->hasArg("passwordAP")) { - jsonWrite(configSetup, "passwordAP", request->getParam("passwordAP")->value()); + jsonWriteStr(configSetup, "passwordAP", request->getParam("passwordAP")->value()); } saveConfig(); // Функция сохранения данных во Flash request->send(200, "text/text", "OK"); // отправляем ответ о выполнении @@ -26,10 +26,10 @@ void WIFI_init() { // --------------------Получаем логин и пароль для web со страницы server.on("/web", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("web_login")) { - jsonWrite(configSetup, "web_login", request->getParam("web_login")->value()); + jsonWriteStr(configSetup, "web_login", request->getParam("web_login")->value()); } if (request->hasArg("web_pass")) { - jsonWrite(configSetup, "web_pass", request->getParam("web_pass")->value()); + jsonWriteStr(configSetup, "web_pass", request->getParam("web_pass")->value()); } saveConfig(); // Функция сохранения данных во Flash //Web_server_init(); @@ -69,7 +69,7 @@ void WIFI_init() { if (WiFi.status() == WL_CONNECT_FAILED) { Serial.println("[E] password is not correct"); tries = 1; - jsonWrite(optionJson, "pass_status", 1); + jsonWriteInt(optionJson, "pass_status", 1); } Serial.print("."); delay(1000); @@ -88,10 +88,10 @@ void WIFI_init() { // о подключении и выводим адрес IP Serial.println(""); Serial.println("[V] WiFi connected"); - Serial.print("[V] IP address: "); + Serial.print("[V] IP address: http://"); Serial.print(WiFi.localIP()); Serial.println(""); - jsonWrite(configJson, "ip", WiFi.localIP().toString()); + jsonWriteStr(configJson, "ip", WiFi.localIP().toString()); } } @@ -108,7 +108,7 @@ bool StartAPMode() { IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); - jsonWrite(configJson, "ip", myIP.toString()); + jsonWriteStr(configJson, "ip", myIP.toString()); if (jsonReadtoInt(optionJson, "pass_status") != 1) { ts.add(ROUTER_SEARCHING, 10 * 1000, [&](void*) { @@ -178,7 +178,7 @@ String scanWIFI() { int8_t dbm = WiFi.RSSI(i); data["dbm"] = dbm; if (ssidMy == jsonRead(configSetup, "ssid")) { - jsonWrite(configJson, "dbm", dbm); + jsonWriteStr(configJson, "dbm", dbm); } } String root; diff --git a/Widgets.ino b/Widgets.ino new file mode 100644 index 00000000..a1aedfa7 --- /dev/null +++ b/Widgets.ino @@ -0,0 +1,49 @@ +//====================================================================================================================== +//===============================================Создание виджетов======================================================= +void createWidget (String widget_name, String page_name, String page_number, String file, String topic) { + + String widget; + widget = readFile(file, 1024); + + if (widget == "Failed") return; + if (widget == "Large") return; + + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "topic", prex + "/" + topic); + #ifdef layout_in_rom + all_widgets += widget + "\r\n"; + #else + addFile("layout.txt", widget); + #endif + widget = ""; +} + +void createChart (String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { + + String widget; + widget = readFile(file, 1024); + + if (widget == "Failed") return; + if (widget == "Large") return; + + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + //jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "series", widget_name); + jsonWriteStr(widget, "maxCount", maxCount); + jsonWriteStr(widget, "topic", prex + "/" + topic); + #ifdef layout_in_rom + all_widgets += widget + "\r\n"; + #else + addFile("layout.txt", widget); + #endif + widget = ""; +} diff --git a/data/config.json b/data/config.json index e16986fa..531271e5 100644 --- a/data/config.json +++ b/data/config.json @@ -1,5 +1,5 @@ { - "SSDP": "MODULES", + "SSDP": "IoTmanager", "chipID": "", "ssidAP": "WiFi", "passwordAP": "", diff --git a/data/configs/dht11.config.txt b/data/configs/dht11.config.txt index cd0bb02f..721a98c0 100644 --- a/data/configs/dht11.config.txt +++ b/data/configs/dht11.config.txt @@ -3,6 +3,8 @@ dhtH DHT11 2 Влажность#DHT,#% Датчики any-data 2 dhtComfort Степень#комфорта: Датчики 3 dhtPerception Восприятие: Датчики 4 dhtDewpoint Точка#росы: Датчики 5 +logging dhtT 1 10 Температура Датчики 6 +logging dhtH 1 10 Влажность Датчики 7 //2 - номер пина датчика //варианты отображения: any-data, progress-round, progress-line, fill-gauge \ No newline at end of file diff --git a/data/js/function.js.gz b/data/js/function.js.gz index 0dd356e1d8e50705437204e9fcdf37465dbc9cd6..de40f1289e8b5a8288da0e68e9c3289c5c925c90 100644 GIT binary patch delta 17036 zcmV($K;yrOjRD+^0S6z82nhA$aj^%Y1b@U)b+Z^&yYHWc3!tIC{yX7a&61-6ccW!+ z8HbZ=k)RsPm<(M5AzMg~5B%)YtQkXxw{z=60e?uN zG5GoPxQC4f>^Po-b|3H-+BgoS^vY^MxN>zE1BHfg6{O=Hj4Va8OqqzHFe;EnB}8AZ zhi&7~7hS?X<0X4ey}-wkjek1|(Jze*=s*Kgmn{U&MI1XNXI4~_cPgSAjE#`2E}8D% ze&$X=jC7h{U=}AUU)aXniLSh$|9@<82g}_^p*X&X5=MVJ7y}Y-2zwkiq8JA(6bEHrz$=|ZL3w7>GLps=yMoX+|it; zF-+D<*){NvUpdLF8##dD+_c*F5ADp=N#ihOd}&J29YP$GMeWWaF@@1Hum*uOaE4(? z6@4vfcv7g3Z2rRY#p^J65r0B(%gJlZTI)iY;ejABn9sou+fnAWsh~6M-v!y5dRMW8 zN}Z-S+HyV?5gAD;H?ujOhM}n%=iDkoJI`TUY+w~*O-N-LF{${xrgc_JdsUY=J|-fH zKCEh563n{g3xl@HAoKBhy%HD+p$i(vy9#yyw1e`5Xf)HF4nrBU4S(L+G#f3RX~A(4 zF!*$QFSs^Rg_(%Eq?3S{#~Aka12A?+ROa|VMc)_Gy-Hg<6&uOCR5BK-kn;+Kf7yZ+6S86_9fVmA}*11Ve4A@93!r;(8n=a=c|j0%(Sj9*03&g?56$f27lg0!ImU5aT12to+!kk z6Dm?}2|v=9mQx4q4;T?>Yfu`InKwUQbq+34_s6D~JB!SE|6si~=N7VILyrTUHc)E+Oaz;g`-3J!`B1St&HL?hCJF zFZiKaWus67&Z3ZVR8mf;Swf6 z^N%S#!Y!lC${>mZY_cwy5ROB4Rm>jnOn3F%Fo4jZJ4@!7nwoj8D}v5l%!&%Dq+(J9 zwg_Vnmq>r=-3j+-941LP??XH_IQCMIQ|G4R%|U-2_kX+rgz^P{r~4AL%{PR{u%^7v zeER+gtaLLVrEYcEi;U{R0MPV!hFuN^{}C>+mLWqJ{1;)0joKXQ@>-JtU8^srLW>ifeisev zaRa-$$u9sItPk#+xu_7YHus%Xrm*Ze1B`8{$A699jnV(&z*tK^=CGS2BD2Ojq$IOG z5B0-s$_^F>ZI~r&GH89qu5QTc%w67CGgc)mw3qVAr|f{oO%&QqOb|=JPuTw4&%UL)97mbE7ApyS{fLB=`$#TTleJhe9qf z!+#Vzsst8;$zkDCRw05#C9%z*H8f_M^h~{u!I{uGzMIC3D_NfD=@P?VIjgZ?E8y0x z14=y!8Lh=Q1lLG%40$AC(U<%=o;_in3*H3Ob#UjzC`D``9$G*rgW{Bz@QPc3T^ja@ zVsA6|R?W;*S$b+0yT zO{a@08kGH*9<1R(-!#W*p`!{r2mO6;7Zu<%vn#i@yyJWz6=--`oRKPUYH;pd5JVOG zn4PB-u#!<&m&+Z=G)68oQtl{rL?>1mhUpE0?Mmr#*=_PvRUUq&07)hLB5-)G>3On*B`Ox6w<;K31@WH%`j(Dh>a&IXga8~U#L{a%_; z2YaD~gw&FxD2w*r$(`kQ$Ivnh@!#c358KG|5YXWK-Gz#tk(-Zj(_XR^S6xBS3SpCM z)6Sb)*}_f_bA-VqSeeY*`xX=(HkVbYh1NE>su~w#o*XjnZES#!)p{pvp?{iFD|{cO z4|vE(YfE}wZ%hTldY3h8W0fFLc%eh0f+1I72XAeLDU$-ALwE@;=%_?Qfeu*}4YlVr zWI&h;EUO^U|<$tYgl3Ki^jVlH}AX`){JFF;sQc?D_qU>2k*6wMfEkpKypiL#|$Ia=x?jR6Ril zN(9eBAKc^Z$}N>I10#_oX~RrIk=wLoc5(N@iG=enFu^IQf80496ejn$mr}HKmKT8e zZ5X-#0<-+5T*gezhktD#|H-i1BU-y7sH9gTo#X9me!NT)%t$wu1-el4yA=f5TghDC z&Dg8GfE4)=mn7)IvIe{8DO>BFGmJ40m$6tbez!c@xLDR#M``(_uPMz?)WA2&MY*Z$ zOF@?6xm}DWGcmayhj*GF%j4xxEZo8lO%{^50#ER0$yBv5mw#kn53G9~gnHyhtgx4- zua^6DiKF{Nwt>k(TCkqmmJbTtaKsNryg%amBitDJy$Ma0RQzbl44rW`LMYEN6y54t z$*fk7C3%%{l*&iFBd>6V@z@T2JmH&f5|#7jYZA3zDN(jze0rhUC)OYQ3580htcg&$ z-c35~GKt)gYJUZc{S9temc&hKUT9ZQ!y+b$mbwJpG9|5LvD>Ow72LdsE|U7l*FiXr zF;@;{g$mzU$s{^e=zry^0{^Cj!!8l4lynI&m-o$DIl{Tz#kWwC|9cbH&4yEQS5B~* za(Bq(fvlY05{I%~RC%lPRM;3N0#9Jfp6)U^(3;h%$$v)fZOO(L+}IjLD@B~<7!WS& z!rCAc@4lAIbTSi8(MZ>YZP>Yyzp=)K!Lb|#E9j}Ck&_>}I{$~$dB5NJ@}hU;wRwl8 z47x_}aRJc^oACLP;^zdmH^Z*8Sp$Ftp zzCaPVGk+|~&Cm|%o*1TKvP-__cfNorNxx9X5^`a~2|FcHRVtO3qx*|qteqQ|O)X2` z9$(w2P>r<1GiqRxWA)s?DVEn^QL|(dXxmUY1l2)90N*5YHtLHUCAkYiT0>%?9dUW6 zabr-5WN(cD?Q932ohQPrl4Yn{$P)JtiM%(*@_)btNfi+&N7<^9+$daNI8)L}6_TRw zPUYGQrR87;iE1J)@{S^TjG7Fop*ALS%Trx{oJ*HTJVc$Ji{2`ay9yg_&B{Yv>nGp5 z{Iu~FsnPwfBh~w>(UwRNPlm$Ol4UCb;1CZNG?*KK#tPAP5iwEBwbE} zB7bY?uZ;@0FPS`zS>gE=WpwEyXLPTsHpZ3bSGG&3KCj5K3R{>LH#9PhHb6d|eUuz2 zF-9ZI&}3nh3j-Z`B_C>(dE(N;8X32qo6P!OJo{{9WK%veq{TW@$y1XX%@|_vE!VD_ z!s*BZ!|il-ds;^rrOmymNmbF@9E||%8h`iTMI?tUgVohNX&EDomG0NAGL-kgUIOjO z&=oh{MA+dqHcsz#!?UXI09>lkPCjR+T&(;0_7CmDefS3tc#M8z=(Cp37d^$x$wb8Q zC=KmLMg>i$&W!+yl>a$Wkr>RkQ6>MHZcwhal!Jq3pRHZ*px+HDsScw;Jxu&?>3^>4 zh5XbsHPFsY7uLfB1TD#y!?AuQT1R}FT2a){!L1OAb}o! zTHqoj#aBF#;7m{fw%00@uvTctjNKd9QK14(ax|1$RX2W{p#P1!l=&e9bQ8>*e?lTs zWY)=0C!^AZz6qmYde79xlS&55UVjZ8rR*~5cC3Cp(eXi}Qz>*sbz5nLW%IO&ehmUq zIgwNp^dG9R!Z{zK&7Pq`*lh0b?!xwMd*{RU>PwzZ=^V|Dsgdn_ZZJXHNr6TmNK70} z)@hMPPUMD>T0iyVO3!kK{QRibXghg3)s+s)r#^1c#J%#S5dixXhbUl334bh|m_pj* z!-xeUB+Ld|Az*z!n(y^=^85P+UL!h<9cil`9#on_K*t<$U@uNErU1)$ zpqa*P`E|tmZ*gJ!e#>e{em2i6{+|SWh1?}lS593jh8BNnVVgIBXMfg9kuzTDbS7)j zGj`2&1xiopwoF_o}i>4j2jJ89ohkj`&WPrTJRTIF2yEmvgoSe!20fP7aVb;gtb%Em>J>N#mP8l*rKL2yGzXQwPxB zVX2oEwc1F?<*>9-g@0#KRj9ekFoT^X4sYjNCgCLvgMr@;gN?T2Xm*CSi@0KzVxuUY zoc>)?Y>l^M@cOyBd$UdFf81tSz8jT}xP7AuTAI5kWdiNE`cXu@%b2i4T@=Bi_;>A9 z+iSnKm<{1AQ@gDdKYhVlcN_NK>Hd-7I=HX4O5Jez>XD_Bdw=aEZF$a7UGmm@`r!?^ z!O6C5C+PvTj*OlVR#)|b5uId)g-UD=wA^eUZe^v~b!W6Gygo|GER)MS*x;MQOS~4h z51-RzkY7Ts>VruyXg9|Ti~ImSufk?MlBIyZhwwRDibg$d!EbK!C-C`M{oe4_F=k8n z`xM83rzSn7k$(q&pTXw^JZQlP1?K1FZO9GD?8$YWVysD68wG1#mE8BQN;&>~69!BG&R=BG z{=i4&{(l?fEYVcG7Pn_J{0ZPx$?CU$(;vv7+^X+QMF#++Ka!#SLPqVe2?%JMX!YBg zX?@VGmikmSF1pbaPQE0Z8xmMF-3`oP{kFf#SAMrijyS?a=SXoDs$QvOK6;dI9tAAK_uyPO^c_c;O5-XNNyEGML9TDS8 zrw$r2ps-)8ji56^X-$bb{kpl_W)CC4s;?{w;DO5It0aj$SRaTmd6v?FCCKVnO@S!o zk$BS*Nm+w1>QJ8@3D%MV6%LR$#h(IbA{9{L($5u@lUmrpK7;q*K2bCRPg^|FHgAF6v221}35gW#?sCg4rmuGYy+g4TmX{b&j z)KIboAw|=NAT;1F{f1fjLEN9#p%TS`LsbX^ED2czIWAjqOw z`5>1fRbq#!HX@z5uCyu^e4Uxci~AiF0Dl*)eVW6o;$D^>D4QTU*I-m<4XT(usJOwl zYa~TeqyjY_ae9731+n0~mt`K}og&fh<{)E$y{sMUt;~ zFTrJjz>pjp#Nc8;k+jUJnTrxmnv zpJ+wQs^QvU&_{)$tc>;I7{6V7@FC*iQ5<2#O5CQLy#XSKha4&e83}Q zUEW_J6X127=cX+gJ?6XpSu&j$Wg04IoLc>w`B1K3@QxlfO{zcPDo;}<8m7B(ej zB;Z1jQUiC^FrB#^R1jz3&Q##1%vm*&G`brwRY!orWsj`r`kr?#<-j0MJ9*gYv!Yu* z>I#MKgDz^DUJeFelLlO{i+|-F@Ie`*TzjsgpFHlik74QmP4@xIiDjEOWg+C!4zlK5 zqCL4RvXB*Ac2WOU(Dl9lPw)Tw{(t@Q?|=EH_y7I<|9t<~@|t($Er|?dX$SgF(0j6D zrT_}p9qw>grXFcHOQ&er*p1c=jRx#f2h9V-qH_AA*j_OsZ<76ctbYs@`s*3VosKX^ z*n02(>#LZw7n^oo!wG*QdJ|4ZrPq2cx3Az;uvVG@ay05qE)|T(=wN!!mM7UF{b?jj z@0EQ^#fejp^6nSTiw%r&Rxp-`cMRGFGsDD;^YaI+&pRLd&Y}&0@=DCPvKD2_Fb7%*LPK$`^OTaQ2s#8ur zA^<1?20V~+57InHXX9+KfI}9lUO6=o#LY#Petd;Bj_Tg9w6VaNlfZ=&n8YN9C~U&5 zInJipqWAI9(NVt;&wH88rCoTZFU`bNknf+G6ppa>IsC6bAAe2oIRY=lV4H+f!$oB+ zZ(u_RvQ0iY_?_6>St+JdGpzR#@CI6w1$}h zPm|F? zaw%5Q0wwE-@Pmb{NrVWQR-&h)z^nGPlk9AfW6G($&VGEF&gkRTew-&``qx30G=70YIy*fq(9@2$HYUkTlXJzVkahiNy2M+r!hd*vHL*!}l>o<#SuI+^S$;YCF?*Yj+OM-&c64;`efnj3ke{c^@ktbihRb%n5fVqg zwFah8aDPab8=y)w_?L*Q$2_zThpb6bG||+u!3|tXw6_*&B{<1SwZniGezAq&0Koo1 z>&gj=v4Dv+&*l?ANm+BE2FGtK1U@Zj%RU8+@Ttn&c2e)nk;T@-|x&X z3Opm~u`qwfaSC_pVGGWWcJ=;jizB9eI?9(uk{2W083`C=n)7ap;4A7pz#Q)|nH=P| zOMf+EVtHv4_N*wUOp|4qZh2nU;Dx<>@s&f?6*&_ea&YtqXPuHMwOw z=+s9_SJGWLc2Rj~X@B?jL@7P$h=^DF`xp(4nVknUui1d#vI3aTa0j@ap!WUi?q^$D zZThF%evxD^L13N+Uq5}4S2l0vC+R7}c>V18H$m-w=YFTXeZTuzyZhPpeSg~@M$_yp zPhsQ#QGD`G7_rh^WEpfs7;3(P&)(`NcQ+RaaGA~fZ^Iqjv%xF;8r*;DZ3K6~8Gr06 zIETLxpUO&o*P$+!|E`-VTFdO~>^xaK9_2}`E={Z*MCiX3^l1UZF*L|x<4UJ7ry>gZ z-{3S^o@CJL%Wq%535Dw(%s^hG$!yF@ty9=#=^U`zCbn64zIpbl`7neYF23>8=Zjq0 z)yhuA;dMfZ+k4yFaBRWI#>pIx$$!>iIxF;$pB9#P0& zAZ(=dmJZ=4A*k?#XiVFqYrbBZ&;%+k6E<~CCviF_;5ucEcwmYe>AVrOQRrUq6Fe^9 z2Dz#^DiO5Chi`8xX;q^odIH&hoZ!GXMW)YefZ%a5&GhK9rohx=R<#&oMwybHmWSGL zMRHFLZxM%$K>;U*SpYrf2Y-OWz9*v#ZvVFm+c}^+=AV93tgDP72BoQ1dyK$nU!@q) z*?ma%DOKD{_xGZ75>cKOn57hkJT(~sSX-c{Z*Ich{fa9)a+OME4l^wnc69wVA6?H= zYX6Q%Ye#Q-8l?TGSA<$9b-vM}64b6vPnz<5w*T7^D%OGnkIpsq)PGiWMylG4LCt+$ z?nYZtFX}`x5fiH-&t_Y)0ehgh>lcr!`B{Eadl#mYutyU=nr7LeX5rwIEs8u8<3Pfm z99~Rn)~&F|_D{k+B7$nLzVNeH<(NHVdiZx7@@@%xTUWoIv+?G1@7-z2HyatE81+6+ zkn1e?WYevxlT|H|?SH6|;I4=o+c%;Oh*zX*6OQcIyuxi0P%OPVWNs%fy|0@>Rp%1J zyp0r1Jk4K>UeqKK>Ux&}5^*W987bzUqt*<`P85iZMxO`xb}7q^$XW_-{VR=V>R!k5 z({+k0hY`AwmP*BJ)ao|tHr#kU#A^cbrvChRg$MgW07PysmVfs*4U@?u@r1~{l6;`V zp`FE2ak$}9(ITnDpdbc@%$tclqM z1>nATBIDt*F@L-iO|2a99ZC_eptK&Nro)ww$C=NMTz_gTQ2E+nw>)KO@QcgmlUihk zVOX&biitDILSf-G+$(HRXU2Hts!-C|YTMWtTDIv{G#&YcFyK`CBf-NQK-zz|6$5vD6*_K{GWUujVZKeruZa1?gu{feJ0HykVK@8`G1iF#G!g?N+uOo1 zTt{#!ure%U4lwDjP*%BkpyCw-Opj3hu;JtrioIIGTb#z}9CnM6mmD}`{?>c5`ye9@ zq<;dc-ToJ|Hn%C_3R%ZyB>*C$WE}+!ER$}a6e$La03zi9iVesjlq=#n2Q?(eAQ%R- z-2vt-AK+Idc*vr%;Gr}?7G@qU;&c|R1 zQ136~<%)0^rg{#Q)V`Uaa!UnqMY4d86@O`l1WVzDCDmVW`J4GPSJpNH|CN~rqGkN! zL$48s!w#x|ZX;&wRu2u4xMv@TD@?(>WPt||>Nn8hY~(Pxt@3yf+tJF%P~FF^ zxDUvOiEKU^r_0M;r`7G7ZmAOQB^zYvdq_|Fp>60dT|Jye$12jc>(K-RZ;*q?>VMc& zpPwx>^+kpjo<juAHVqt6mpC#NKmJKzTN?rsL7zBel?|$UJy0CW$_BN4Jy0Cv z$_91snxmrVS2n2o*8|02v20KeuDym7FAITPspnaJ7_>Pq;RN$kt}MOBGL5drnKO2_LKF;0Ct(PlBhzm_hQoX~e7)b;t%E2BUmC;Vq=AOF;c0p-*h=4v zL`h=?9cZMC;=_1ce7;>Og$;AWjqndJZ}ju6jqAH%*c)BB-NnVrhKV)y z!U>9D8P|Et@H=>G|89Eo;KxBrh9{i}nLOjdYNs*$ojpekwIZ|XZBixv9JCp=sL-sc zi@HbFLUOC)x~&ByO-aD25`yATIGRHwOGe;gD+3|(kxk%$?P^3A>VJ4J7$`<{R~Gd) z2BTFI4%)vBuEHd!-ywGqHS}U>ogVCV(&j1N!^udnkNzQCuyx(^pnXi?$Mi2iIt+|# z4qbpSKt>4=ZY6GL{fuwcE5K1m5C^r!YSe?wk1}iSW0{ zVwsLHb_-dNF0*+*{C_PN`pT>658YpzwP!R9m4bwBSf7eV#vwUBNfzP-Cs&-Kt**jf zSj`8&knRJnCGqxNjB_9?5bBMszEC6js^EP^K*f8gF$CK$cU$JpLKD*bY>r{}x#doG zw@l&GR3^>@^gsg&ZxPv#pQSE*BznUh?_4i(MbzL9MO5Q*kZOj1OWsG46XR)r@BSVf=;b6V>}tZ>x7N$3g(xL+%V zg@tx+FbliZ^`lx;_vWp*S)2>I?WO@QeyfNVuG?7z7%x+eNiaqfjG%4A!63}g?SQ;n z4s`iw^1}#K@qfs~)uO`$#+N*uO@Kk?mAL%}ll&H6Of1!N(ME(GOqkD1ohBR{>PQiE zC=nQjaS@u^&7Vln0xdN?G-v_8xU*$H6jdo~getI7)xD0v;CSI~bf04ky6WrPsA1mb ztFKn(8~JAS-lwIz^kyMZakTF1=avJc+8w#Wr55X~e=O&&ii}#A=B9B{i&**_kD7Y> z!BVS2qTYTa)DINz^qQegi^OyLflrG)e7KWwDHMNkDVQ~epYoxD#7h;7%3I3_Oy#<# zzFpkLHI*$^+)}#2W|tJ{N`B=#DqH+ISCrY0=Z3PY+~Ngg&2i)V$;QyXUQhpeJ*|H| z*|hTkZYR5g4|qA1HfQDT{u{rV%;|b>CaaR~Vlu=_^d7}~N#KruZT*;B=2XR1DRtAyZ zp`oOE7Qz)ruBp05kO)q)bGy`7ajTp`>)_)$af>do6S~~YY7-UO)(Uym64me9rYR@C zt&x{RL8TrE-&;?Tn$qK@Zzxq>G?f|>9$J4vN7A{mYDAho+A~HTQ%<;8hAZnSS{qRn z$`x0rQhq=I+8(8|SVafY+mg!zBYP9|LoQ(43hMHQ!8shr*?G%~3yaUNS59kJZsdCK z+;GpyA-YJPW5p_yBiUL^SZ^T#qs9$)RUk-=ynrtwUZvHF4s6*VH-!Ukc>r6o@Vb8< z0&?GGWS3O?L5O?oNXu2YegYEhQ zTOHXLl(Ga=+f=GWrwJOCm9kUq<0L(sLQX_kVn}q*RTce7ZTAv1`P%GBFJKw-C=<4l z$C&ZR!@iP>(W%%$%WUPIA%+3!!Ki;mlW%8Jbd=I?27`!j5*4B;kSQEtt?bnuHK;4o z$HvIm>}6F}HS>6bSMA}b;hIU=NTz2!h%q}<-^kN$<(B8$4ryAAhzy;0Oor9b8avN_ z+1T5zu-|+e?OIz+ZZ_O&cI2mGy1l5e%#=~C0PSL-EB6QU&(M){wX>Xlcqo6c!jXOJ ziorSVN5bdR#Udly4F&hgVX*`Y;&oImuEU;M+0K@B8;)}1O(ud(7UVJ9iP%uZ&8?%O#F`Dx zljO(A=rR%>@U|;m6-x>L=r)oMu126<96HHa%(1Rx6i3iX_Hgj)I;L={aoGXfMUJueT$5rv%}X@othWwTRdnDEH1K~bkr*qekQ+Kc zZiw6h4@9g@`fRQhUK!?(ai~cxl>C{FxTByJm@nh^idZ}6Cz%C^2jv1KOV(%A1la?A zGlM}BN1Nz?Pq$wAz*}YSa0}{P)mSK0tms*QgiUssH>pKO%Rnji0LUB`R!&EnykcCYU3&uxWbJoTyGd#=COlYv3&4Q z=rGU8LuKxx$AWB~6Q*6E3wW{EbEB~HklDdU$QN-$YCjQBO^i^a&f3AiM8Ix@Dx#=o z{>Jf4%)ZR!F>HU#XuN8Gti!1|(r^Q>h?>^FBN9X!M4*)Feod}dk6WR|r6SIi%DO$7FS}D91qp;jy zbTA0uC>jyTE$|lRMZ_KjXiG=FLmxpGKk8dr`b-VMw&IoI}Qq zN7#p8Htoh|`4W(Do&+a=hhV5)mBPM>H z`f%5(8ClGYUe!N(i9y)RCu&p?h4)BDpm zU*oq|LdP#BnN24L3>E6}2X%;;Us0YmG~=rDKxSO8$ykG{Q0v1WRs_lPu(rq3+XuQL zt$%+nphRzNR^nXM;~;E@4LNxP*=`$XuL(35Zn)wX*1gG9!ERTq${mSAxPFsaO;Y!Y z9z?ba9GGfO4t#(O9W9ZgAsQGS=%whZB8^`4v_K~ruQ=c1?RMb_5BlM9I+qf>mPCDh z;{wWbct|-+B)FPHNfj{?qHSWNXoff-y%K+-WQA)pwlkw-(+?k+flTU3*DRY?gvK=d zUkQ?UBmjQkI=-%sYf^fkwsHzW-Hn@F^PNCFPSC>_PRRbno>}ltUM5udf+B(!TJ*2V zz{#A)0#3j9fOGXhp|%S!sjDo&^h*)&9Tmb)cCj2C^XTEAc>dz$cW=!8!}XL@EOweqO5^6dA5K%3j~E7KDC9Wl-Jf3soqp(#DI}9??wHQoDtL!V(xnBp zhbXAsoi6+Qu;qBv^68AMS8UJmwBdiH=d(&O)pZr;T)y(0w@(=HRt#q~nH0j0kvj9Q zxyHmY(c{|6pjux&eIpk}y~LptJWkJHTsTcJyOfz>X9<#7ju!}JlIt5;cPMKy2-?e} z2_1|RsIWL4O-r`3x;ybU=M4{|aSU8L2CN0a;7iOj3Jkmm`_YSp{Uav=u5N!rNvGg@ zz(4e&Zl@D``**^>mK~mv7FCEldgGtW^6wVYExmO3OB2>_tF&;ku50BK9Bb+1uhtx*s*EO$sYhz&rJRhxTcUMi@38DcjS1x&( zEtWo{+ysn;GK-ywBE`(C%iS{EBHw~TDKILXI1r1ox2Lc0GV3Uti8I#1E6!h2PP_p1sY*qh)cjIo)8 z)7{&fM_+vXG%9RLWDymqP<&vNy=!)j*iG##dwgW~#wovace)YYawd^;&3|$?*XH>Z zOSmzQugtSFFK?c%29LOg1TZq$|Gbj_w~?&nfP#Max)`}GJ~kV^w8?3=iMG%N{9;*( ziCmCoa>_dB6J|KxSCu%^Zm%!UFf=WUI8@d77ng6CrfZ=Nf8K7pVy#QjvdEsm{0*_5 z4C-LrC=pu3_PvIDOp%F&4u6a`1qpY3(qLUtXvtYZ=wjs+W2T76f+|e_DL;d(J>gBJ zdn=Q*UloMsNji!76ZIpz!IuQ0Yxffm^C{@{(YMEjsp*!Zbe7kYqmmi1o;so(#U3t& zca%kPn!QbGhL4k3I+_5vYtI<>=G8q&Af7%9Kz0vS=g#*S+<4!oM}H~ej%z=k z%hgRY_4&tr35!j$mzp!--4d)j3YSX*C5xAG$dub zZ8ay7#?cIdCguz&w14b0A9SMr)mqITINCqxG(TM%z^4uXpLUv`tqtHa2Y}By&Ck~c z@VNuP=bh$OM?#>r5gNE^YiLEi$|%~|bDpP@Vhk?$smTTd_`8gMiN7M3wH~yBdnX2* zD#yAbm5US59L}KKNPC4MN(e7aV4c||R3=GrRf-xKhvd**3V&ngjB4(g6|4^QGx_3F z>3Jvu)}gOHV}XMyn`ZYavNayFCi_Yp;V%BwD;+PWaXLbcQ-CRPjU%SvrvZB@Df??_ zg&m9J42t-S=m_WNn3C5rj}wYhGFMDkiFX?6&*HPilzvnXL3lvQAJ;e+32x=VNHwYt zM5JOo5b1ePoPUUvYZZ?~{&C|ok-IIOg_7(1Qd*slrqf8Ox2O#g4E8DfOyDM|b>jQv zEfVGP^yo-kbMC$07J1}%sd7FLYOBN1_{Xz(YraU|CctyNZ3CX#z+a0MK?gmm-|Ad^ z@kOW8IXHrSadMESKP3lS-yF8O_aFS-;Q`Y_VVuOzZ+}0CgXTRTLQMR7m%y&yHGPDh z(K_d5JyVVZi)MLR_&_-rltAo8@(==Erg_e3f)9Z|?yH}-(>qmC!&IZMG`FgXF% z{T65wj{AE1LFbd^R$o}lA*g?V(kNCCuxsnBE`OcJb|^*!2e>sFm?K;yXr_sof=;kB zK22vJ8jqD_53CIgQl|=vRFb_OiEq>j-3ZyH2b$BDt$iBTn7(x77mkZwL--WyhvTu2 zcLutPKGX1EiUYY4Jz)5o?zY$91AssfBns%utzhYCNLRjLIv=#hdAK1TOO!2 zK%E2AKz0Tg)@vii&sF_3a!-})IRtm=zrdWzaDhtUo;fO3M3cvlnE&8%P)hlL7B8dHQb+ zc*5RlJTkQx+^c**>PJ3}#dzdSg*V1DawG9HBaEZRt?|id@n~7=FzXTk+d}n>3x8oN zhOZ1!d#EcfSsr^`B#)G*tkIk+2mm%H?dFYIyFzl3Wcp}2Wo+fzPlS<>d+{RDVmk4{ zO+CnwODbv!G!f|hhK~_UM*KYStz0qy?mX{l9%bs@vHe7a7t#e?Z31>snv8YhkyFdf2g;Q zPhDPH1{_0ZF@B}jDouc0-r()F5=;uC=@N+-oAaiU4*113+s132wdJHoe?wx9zcSTYv8eX&jnLjiF1cF${M?BbmVtw_-(xSukwRxae@P6S6o! za6s5Ul-Yo-H+Y*WU2Cpje;l+i28FzFf}(P^Xk5nqG7gJ~1Mc2Kn=Es5>mLoGkArA8 z6xatw1?RJ4BNB!T%$+gKU_I)Cc24>$>=_0>7(}n0e*Ngr#sju<%74X{>HaS2wR}OxB4k}j0s;bIjL=2DR^kSk>~z~0%MW3Ev!2a;w4aDWX>5e_zI zSi>mRaqxAX;sPpTr*UBBBUi%K2KfR0;Q>{@#8IQ2P|l^VWDYoz^Py)PEc`)R2Hx`6Q~x z+7&373P(%$#DDBP$gvS|E$Rs#I~67z(lZv0GN?ZW@q7ZZ1{}#M%Wwpn=VQr)@e4nB z96x4@@+wx}?g!f`3p?wmDc3XL8!p#zR4{%i%#uzaoMmBxR`s4+0Un6c*? zXnF&fsSDkA(Lr~N>D9iQll9H%XiN@tH1h&M9g#Y>xqlSqIohKs^y#jppty@o2Vn!C zH^OEp;?OB~&G2m;tJK;3t*^kyEq$q6yOirYzbcEUo?wzmpRorFQ?yJ6EQBBMFL}bUa7gWpe zt5(cjtA9qgVP;PG%SQ!&0=6t$mFlv*aIk2m`XiLTgIxVLvzXRVBAmVH0d=O{!c(!j zAFYm$$~Ky`(dgBczS~5w@yg;=K$*gG?^`s5ZU8i3Z*U-)v6{Ih)e^dUjQ!T+rL4G- zbZA7;3>}9zX-31wzDiHohDo%>ParBYKXkIvxPO^i8n(^Y#Ik!>ccO*FoYYE;w#2D0 zGWR5^_Z`wXO&f8gl}yIGbJxU0eV)0@LvMBiya~=UXB7fg(Ql?=uIsIiD+wudhm9Gu zPK)j&asQIQ9j-LD^0Q!K76bS}stSki;Qy~1yThyD6^!asF>z3@6eoIsXnzPLK5tlH zmw%zuH2e*kUBRih+oh-w=|n|(gdvf0%R*tx$l@Eldlxm(tmf(pj=*E2>Jl8;$) zh1chyD2qfM$97wqwX89oUHHUeQ<;FiLVqLTbqQt<{*MH+KivPY1mlfD5?H3GO2t4s z{bD&#jv)^J;K4w-l}ND|o5)&bARP`r;*Ol7Bu=daDR(5iW~_c@7|r6lSI-}3r$B3o zNFSrTpzCV`fAjQDZyvpR`sn8HU3jpAm#F&Hdus@UG2G+*H3ae)?#n#}pzDUxU4QQ- zlh`fhjS>^T`sxdmC7(Zu*~ z#8bg&_I8wW#gBExajt4CDEmPP6#uMh%@+w~hc8tVzeBwXx^QB3@4!hyMkGqMyMqHm z$@b}6z&VP!31Gb@qUe}1AgwXBKYv+dr-=}hS{YeX{0Zp)VxYeDFV*Ki_k}|NaD~ZH zc5z1$6f~ZWE|Z09%U`G|edLyBdGeUBRb!;ZFx=SS=-tDuxpR6Z z#%9Q5k??l`oLqOpDS@721B&`_5eJuXum%6sTL?hOrG(M?J3K3y2!h4&;eVU#S#nXE zgFqY4_qOn_?tZc5H({CU${pl)Z>NCet0dE zCD7=S0tSX3hYjDT>3C=HMTYOV(mOySKbgja-Wc@=2pusG@-L~}FiWHCCYwWx6)L4Sw-GhoIR7#y#BofpHY*#kciDvM%7BU@RLOzl=Z4&!<2K2tkUL7CS z;Dc#b#ph=GFCXvL_D0R4;bi|^_p0vu{D*ehN-mNyLD6fFG3U{4?&J07w8& z;p1{?SC<}^OSiccCV$u~TZ+g?#pyDK`tvN0$Mo$nY~`h8u}pz|@?N_=ny0Pf6z-Tq zjECE%R&A7%;NM2n=Jt7&#|MjYqGB<@j5K=|quL}8t7uY)#riNXr(}j?wTDoWO6LCX z5XyXBTjGyV9BE<>6P-n#wGLuf{BFx#wnk^mlWfsq%Piw5cYmwHa%3suLYjQAJq9MKhCe7*fFJx42RxnNL9dygR z8)U10NHXkXKwj2YKv^5HbK?S*z zFa874RVyK1S7wBN)@J^ki z`6&=Yib^QMUv=jp`xYAe74w8E8)vcr8&Xfr$T2|jDStxEU_IRVfBzYF4ujh%*QNIX z!+LG2(;=rFdo!CYs`m2x|NH*`y#F7+{5$yjzrFw8@BjM#ujqCscCSnlZi*`fhhSO) zb9ai6{|^Im7t04IUGGDkh8C%+J+l5GxGvs2>mp9R;91waz(UcQeSe}0%9qBu-`Ako!j2TU?o&#@=&j{`aG4I{70E z3l)%Y%5i_(rSjAuZK*m{?vz6E&K46&%}i$Y%4u6NLEe~|LIWE}6|5I*cYYD%8H_Q& zz`|A^-Yb~Q74QsBERK_XNEhmldx#Qif$6Jh320cOki9N}(_dtRMp)BeYYHS~}$)D5>uqAb{SOFQbw&XQpp87b8cEeGo>-`N zlC^&*psm!NS{hr?8;#0j8Up7yC4Ay`laWf0K?pSL^_A|thP8|_8j6DN!+JPmQ7O0j*bg61v-w;Y{Td3kS delta 16884 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 z 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 Ad6rp{#Q8 zK=~^Om>!}0VZ+I%6nnLRf449W;|1&%B`-N}$oy^T&0Yo>aUc~??e@QzwYg0ZSI9ax zD*+H0CF>|?V3~9SrARSY1Q03rQEWgKp;!^mIjA8y2Ej0x?e;NM_z=G;!9x}m1rMbG zDt5CQpp?o=Aa&kYofMpL%|H>#z`i2%gW&^srTO$saXto9fO>x+e=k>r!!XrzsH85N z87j9_5LYA%_*juAX>&hW#~2HaM(c=&~3zw-C9CJ zq^?kFp!y3M<_c3VFIi9m2=yCiaW;0C+*Wx!i0x=)WT@`rR@?{V!$h(ePvYf8ztids zOt(~t_ksewv!-kPnMIK0sMh;vk6+vSjwGUR+d^)};f7TOw!Twp_Y{G;(E4!YZ zr+!g^=D08DK66IOl2NkCjv^5x%N^y4L_lG;EV8ppF*cs7G3e~<7bLQxTqVnd(205T ztg~t8h`Pj)srd0v0_$!FOay)6kX1IQ-t|CnEGrw-*7ZPfkSiP1{cDbjqF>pd9$XI; zhsCl%J-qfBe^R_G1a_sKXU#@Me$OTpd4r3M}v5!|IRJGy^Rl9&Rt5XsX>15C>Wf~m;G~f)p zH__3v^F__C?T$v-X!Lfku~P?84!$%-qiF*TZ~c?_e@L*EWiJv1jTv;HkunYs!b$y7 zES=fwU*c&4yYd_6h#USNVBYBGTbtB(e7`@wa=VL*mkkqZ?1kgy!!oY(m{IQFt^K>{ z&4V8YEg7D4B4qN63#*;R@OSncG1Q98s<%m%__Nn$)S^POsxImtSqsUnj_S4+kTfM8 zt4aupe?#GD4v{Pwfs3sSgv>`afdjUy5n!m};c%!J)g4*X-x!QmO*m-(Hn<9tpniwk zMbOZTrFD9++ew?Jcn>Ed!9My2aKYAf)BW}lg&)(u0O>F=vN?1C!T=csK)98-q4hJq zS+4*`AweAQqWP+p9I2wv6qQbJeAMuyYM;RTe?+)%=947C-$&^(o?z@2vLan3i-G@J zF!YsI(;s@jHfzsl8Yu+{-LPdU9vO$^>^Mrr3r?muM_XNmzp$DQej(ilTub8ZJs;;l zSRm9J-GNXemQ}&~ihzpuP-6(TU+$L7orNZ(+35nq>~qWQ-cFIisi{ny3Fv_a6y74R ze;+>!U6hgN4ST$Ey~q_ogF6&ajf;^RoKYK$D0GGyiH2ndq${aX8LI7up($2Qt2!V> zZkVR=OUWcfB#El|6=GGC1OclERAEkQoro2V`Zoz(;Q;q*#jvo@UK-58u66yW7S+9# zR@^Mkh23`3fET}2#0%H$ECP%dsm3H2eN#&CLJua)XU0ww4i0ss2-=qj^!+do&F$t-Bxr$_ znjRXofS=#lvLA}7$6#>0a5uWoF$P`rb#Bx!Z}ZhxEAx$fvzFece}%jB zW+72=wC?NYmII{P9l67$=Ig9~=dOy3nw#dPaZ>YG`Wug$di%jrt3smQek9b76z}w! zp-%I}bNhi$^F4gLFsP0lTD{3{6e9I{m#vCQee?K)VIi0`hMy`!2Z@&|7*%O4BQTZg zp87VujcY1NSKLy%!e*Bg=}La(3Og!Ef1NAJ?5E_D(J2~#5pE~DgO7MQ6*gz(?*1FU zn#}2z-b_}dvWv+OFVTAx?*1^Yrb>bFXVkdODnbjsLw5=5?RZCRAZ=0r^{I*735;>K6Abf92lGGF)H_L`n zpCrbR?Y{t45^hqdjBfG3A8wWw^2>MQbCfLb>7!Rmu-2K-=SZ9;)a-dRub2 zXJl`pe#ixkTR~m^Fg$|;IXP=tabfWp_R4AP%8guq51t$DIXOfZ>2s`DWpX52iwWy3 zBw*CI;f@LfiIErZWu#PTwW0%CHpoojfLrdvmdw4b`+(f{3E5|Oq%E@vUbWNeM(v}k z3dw8d^dMWNwN7aLsx0<}F+Fd03F6*82~Ag|aj;##XR9L{!$OvTYMV;6=rlpYvQl=c zeVn9!XOqu~C<_dU4!WwMKdJ3rfF@s?OVSHi#yrY|t>7_cJo2!wWI8?(J7}4#+%v>5 zKs^}Mc>3*phK^Di&TtqIPJ&!C1u}&rtQEbwg9deF`q&s5n@d@hRn1Dg!K?Og&~VM9 zXe86O9>ka(s&C|Jw{pw#ZHF|iMnr~AJSM|`>S&FfSAN;p+b*}?$~M}ywwl~*xYz8+ zPx*9vL1URHqg(;n#X?u^59XhtBk5{qIsNcZV1)zw))j+u+>eCMXK9*{?S_JT<*->|X7cw^yl5Rq$mZ^U zs88a-{&Z#qE~c+o{V++ET%A8v-eOALi5DSxU1`mhF^nQVq)#{%O{vnkg+1#w_clVT z;rOZ?SWNF~S>JG!BX2ShY%(X0;ZDScDsFBa9VOOma27>BPRAF4@PM~n>8e;#06@2q zd~h`a_2SS;&SH*r9iupcRGx{7NLo3M%A=_K_PRx4?Z7Ym+{kYlT;a`D5s7 zQu8H$rX%hss5$1#_`M?5&e?Hd0pdZqK*^HzSv5iSfZxPm(8SRuI^ff-Up(-CR@pn; z!uc%DQy8AS&-HBOf(XBN`;0VCsnRt!bAw5lOfaYW(ECst{c7nyhjqIshjuhS5laXo z+&97{mDn2?m6Oy}SHJogRmn2dQQ5Rh6xBt9Ha)STCBKkJib0mqt{ZS7tc$F?tWKn; zvg%+@`IM$kSZ48h;5bWV!P3cpLxy%gkUJD*Eqq=(JH|`BhQTSsN-?!vP$<3%gy5Pw zFhYykxTwI3s<9Dvs^AtYZGb7&rW{{ajIy6>l>H=7mZXfapH^WE2-}4)pzOv^RrnGW zHbYlA)Iyz2kR_U|#8qtLDi*lHjVWAj7+dDCgIlq9@KETml9PwZ+((ap1=%_$OuIrC z@O*K}jl#}DW(S`jU&Ilq%ZY$$VuT`f)((dz0(Jsa5e0qoH;!jw_GK=QVPi()RRd%l zPQ{Ui8+b+3w80&bAkrWLrBpB1KpvP0Gg_Y4f zFU1;3?X6xFzBFqT9tx&^vJ(Ut1+Ji07qYI^O5rshh2;jLgFygC(FjN;M>T>})hO3Y z|0K%%hM$e$ucOFEU-VZAv{-s+&|nAkMvz9+AU9Df+y}<{VzXpS`C!8b<`F@^N|tYY z3D5_C{vIZGu%&*+lZhxB%SDQFquLe>bI2}+SSes#BKA@{9hSs@;34co)Apx#ghn2- zG`&7fmdIU>vy1seN2pUpHD<x&Z8|#oq7{wc^Kp2)^4`IZ_FOqDj&~r)HP{?p{CX{=!&%deUB2owONUCRS!MC?KkA) z5oEh{hq&DhS2l1)E+Vg@p)D_yf}UJ)A8@P8#p;*kLOf$R9XI<86Sf!fL_ z2z4)P_RMzz^*BKfUpOKA7kg&jrMyh2@D)V_&$SqTTor+nIgbULeklXa)rYy-F2JO& zvH;UBdBAs62tV1ya(u+2hlAq9tJmMXGy9iENM$@rqr3Xxs=9}#FaAF8e*W22^cV{~ zSIP5kc~P&tXsf*FetFS@@}h?(YHZK^&CsLQkClr$NIbIndckl#B^8UECX>>*Iqyfa z*ySUChJhJ!IZpZy7Uy1P;Fre~lF2o5Qyb z?2_YY!%MHsD#=vWRh)C#%5&a6VZ>W8oYiDf2tNku%)jOu6U#)8Yb%3lef{j6Tp0Bd zhfeS~J%@4OEXM3oW`><5NM;#cAe2dNU}W8Yp{&IqXfLBCbTEmaLV7Zu6>Mj9cj9fX zG(3#PF>vh|uoeV^uQ1anFz_PmM?VnukDLg&x(y|rg6|&x&<}c@j`!`~3IAGlct%=O zA@1mne>%^;OJ`lZbofgX)~{PwI9b=Vate;Mbn;j0kO+zq2nx14q%>CRw!LOWl@K;( zH@jYOcD=IM^(to9Gp~7TV_^k6AFXNkR!!Rpq5&&cEP0)z%QB?g1dN3;i=7Dq#mubB z-P|JIfFveyUPIqtb9)J1rS&-Y5$Ra9Iq4>Zkd)Mq5p_|%Q_W0QDjZ=Qyn#FFe&GRdkaAO`{nP+KU-aK6m9&rr`U~IDgStb8(BU#Gwf`bun^Xd~7y+ zX_M1#6K$al`1!ItCURZ@B;=Z+^4_6Q&c3{O$D~*Db(C^fKy)ep6?h0k@+O-%KrQ7e z3)lqL5Me2JuoxxLEsb+f(1i&GZFtEpl3DuV4c%Idi zdyN@qojM{qV84ufHH?faLOh zd>A9{xb}-_hS-viI$qv-(lV_Y81IM|te-y^47SggXA;*u3eG7WF z^JL(R--0wc){vCRvDKVN8b>qqnwaS#*Rs=m*a-$#Yc+r9X#cR&{A_IipE&@0)@gpe zHh|9^06yFMyj8vogKtw9W1CbuJ#ED25Lh(rCA2&V|x!b~7D0!u?q^=?CRbc)2r`zqtV>ugD*10zW{!j zUB9+(qdy}Ry5aRHudG$HDrcW7T9bB7?5$5mj!B91QIy!9Kt+HhgTg+|gqpx)pa~Vg z$3EhK*KWD5)&SM)OasX&U|6q>7(>Gk2`v2!5E`%qe&}`C-Y`daPm<)vIHGKee<6pD zn2s+pCEuzqB0~b@K+wd9J7`K8e;!bcz6c7f)f?2_`_${*hrb?n zAIL95zd@ju$=Bb!lb9O_gG&%%jW#~~tn>&InhuT;ce@W@*xXjsZ$J-=F(AL~7YKZ6 zph6KgetGt94S2#zXfign7u>6SfA$yzWg3gg*qy*_g2~Uu;z2=}^iEon<8k_US?e(C z;sM)2^^6Ol8^TwHsQs#yZzqqvE>a%KQ`TtC6$Ahqly*)=T~jWlMl^don=!UB?cKmg z$V%}dk~uo@!c9w%BbQXv5@;gI`N!8urb@I^>(E!k#fj=g&26vQ-I0Tmf4;L^R`2ug zMA2o`G?3K!?)WtHI$iINApdl~_^jh~I(_=j19J5T1q0T2Dz+GF#?`E zm!-7e|CQY0x7iUW6Gn1!e;nmvjPcgCTG6hELiF-7o=30ax#L$;hkZiEobA7~KCRVs z27>y}f2g;QPF%i51{_0ZF@B{t7EORX-r()F5=?TV=@E(NoAaiUZsYkjTgDrdwdJ~U z%W3egSJ*r(^DA*-CIJ29YN-fwhB?P+P8Z$nEY49i&#D9EZJ3`be+L2PxK$jvjWQAB za-Ip$(kKIsIDAj(cJX{q=Ch0KcH18NmZklUL*GC?U zMF;7&&*A{V0b&0@=CHM1j%})Rt+|4I*K1?s1bO3ldF5>0B#QfG9Oe-R+2b(jjQ4s3r?K-<|j+oiPXuuKBf`(vf3v(2BY-|Atf7)6)X4@_&8HFRcwXZXc zVt&!ygDWeJNe(7%K97cF8#|OO&%4J@o`00pQERXqPmXg-P=j3U%5F;i4D5GH{G{u1o8td_m zKq=&r;J)5nf5^ljd!i>CpvmTHx>QzBEc3oHMZS1i`Y`=OHq!u9#H3T;GhR%Goe~iz zo;u#CNiU^&dHLL`v+!tBMKw<36}cgA8YV^2Jv)7}MiC3-FRRy52Ps4p5k-_GO0NY=l_n1AfA8+K0JYEHJa0|LvstYoyZYUr zp@syk%BMj+)DA4sOt=TaCuZ+Kjtz)wQBUyLsW2at{+w`>LH!Ac=Tne1;7C@vaRb;q zcO?_XFZ|>u`-JVFt5|)zA8e=W!mOjFSkHiOI0}bB&SWDuOFD&cmbnR%zpJt&r*|5o z#?bg;e@0Aepuq@WrY>~fdAHIDCI$O$K{g{N;|aNa(aduMbx7*m=294yXg?gkOm{5> z#T{%q^cw)Z;WvE|WrZB1-iwUx447%JUMfkJrS@||kug>?5!a;=h>U!zvSGoOXxVc| z0;aMpdVr{3x{~*`VZ?y1<<69oYbQTikC39Ye+e)-{h!hiYS*pHvf5W+j~$Y)2IY!s zTF$2;r<=W?T83Y>V)j}!{0;L-%3nUoS;4bC)T#uH#f5`KGu0oy{2k=#znR6fjuPRb zOb@7Y^%fqB)%|33R8O`nq>V|H~?tC-rztoBMfs(9b7Y5 ze`3V4CNE{hjidwmiDu~Tx=Aw{HuhC`$~FvnHGVu%nfamPl_t5=(y++ICYIg9x)aT% zlcZK+v;|Iuk+~~Tz2}h5Y1)V@tzhsKH_H?rwOa_mQS%rXA^qZ-e>w2r> zN}UPaVPgiZlX*KyynIRE4p*96`B^YAf9Vi@kgCGbCH((wV`p?Vx`I)iC?*c-6`~st z5$%tlq|ApC*kvd+%~ic-PjKq(b|IEQJXP@tVMyeXkt%E%xo3mR%bh1chyC<{dP!FF4kwX89o9r(mzQ;~qaM(?_H31%1mj|8(f+WWW!QyM$N zvrJQ!ih*|e`Esb-85~}%!=ZA9kYX`5k+sb5FB~+(9q&a+oLUJ|>`3@}SpCc~2E%u6 zUOY)ofYu_B^hEjY*4GC9?%AK-e?5Nl?D5UvyYOI#+)(wa_tppqW3 zK-UeWyWUGCv0Ka=rPF=$^_M71zIYn4Z9aTpAsjx)>-NP{X@L-*V4m##TF?p_)C#%a zsvVHa*aE@Yb1X!<$*e|9GNNbGkkJIEN5`t1IA&ZJX0sWs3)wjWg`uyjC zFoOrKFgi@m?p?48_UHGrwLI6rGC5+ZD@vLMb@Y17$ zcggeUytV*=HeBp>@vq)qy{-*xC86Z_SOK6W$;Ub*cLLM6g!Ov*TvQM>V-8=qM&>amGDjUzW*&*jBz^p{CfRuj!$j@33jYhp}wi zpqwJ2;!E`G7NrQxDtwnLn3oU+8BpSx<)W8?<{>V<^SQGpA$*619g= zkV+QiK@F7of4sKDpP)F>#LOEy_c?1F#IX3?mb+|?PnX9@+G5Kr<0-e>VL7r8C!qic zk+=_(Okse>DJ;>@-#?g*=RZojN>{%pQI^5ErmZX&C2s_UXsKBScZ#5qn7$|)AwGnD zvLYA;{F}h;;2N~V09KQd*-?>_c<7ZD^jxLdg#L7af2%d!A1~36UVoG3^!gVvsy8c` zru7cG<=zdl)j#s$!L^uTbTYI#0LsK`dfEHpb9Q)LQF#e7xETMKywAo;r7g$6ByEj? zVNgM)WDM7sxXLd5!=}5`9c+Ls=M!#N?)g~Ue#E|o#(u@@*2>12EWk$8Q!{W3kbH_zGg$Yx|KERxox|X^ zi*@OJz_4EHb~@y=V{c}&Mb%#Z@P9x2pAY}zmwyL;|F;kS`@>&9{1x5q#O{@;txa(y z=f+A)VD3&4sQ!^>?qc}>rR#mH)6gPSwMW)Je+1XXTgkeJlh1n;Z`X=d@RY=d#72Or z`eMfc=|X1_k=1xKV~yY`XqNoK&@ zgk6{x)p|8N=f9&R5$C+eo+Y7YxM08+sP+_1WAN;Es=Wyb{6uuR3Fkm>Wf}X*RGs>3 zfBHs!Bqzq=rp5&}N5-gvv<#YT&O}s+Nw~mOTjJ3 jb; + JsonArray& arr = jb.createArray(); + JsonObject& obj1 = jb.createObject(); + + obj1[value1] = 1; + obj1[value2] = 2; + obj1[value3] = 3; + + arr.add(obj1); + + arr.printTo(json); + + return json; +} +*/ //=============================================CONFIG=========================================================== void saveConfig () { writeFile("config.json", configSetup); @@ -159,7 +179,7 @@ String safeDataToFile(String data, String Folder) // addFile(fileName, GetTime() + "/" + data); Serial.println(fileName); - jsonWrite(configJson, "test", fileName); + jsonWriteStr(configJson, "test", fileName); } // ------------- Чтение файла в строку String readFile(String fileName, size_t len ) { @@ -218,9 +238,8 @@ String readFileString(String fileName, String found) return "Failed"; } if (configFile.find(found.c_str())) { - return configFile.readStringUntil('\r\n'); //'\r' + //return configFile.readStringUntil('\r'); //'\r' } - //return "|-|-|"; configFile.close(); } @@ -260,7 +279,7 @@ void led_blink(int pin, int fq, String blink_satus) { void getMemoryLoad(String text) { #ifdef ESP8266 - int all_memory = 53312; + int all_memory = 52864; #endif #ifdef ESP32 int all_memory = 362868; @@ -276,19 +295,19 @@ void getMemoryLoad(String text) { } //esp32 full memory = 362868 k bytes -//esp8266 full memory = 53312 k bytes +//esp8266 full memory = 52864 k bytes //=================================================================== /* void web_print (String text) { if (WiFi.status() == WL_CONNECTED) { - jsonWrite(json, "test1", jsonRead(json, "test2")); - jsonWrite(json, "test2", jsonRead(json, "test3")); - jsonWrite(json, "test3", jsonRead(json, "test4")); - jsonWrite(json, "test4", jsonRead(json, "test5")); - jsonWrite(json, "test5", jsonRead(json, "test6")); + jsonWriteStr(json, "test1", jsonRead(json, "test2")); + jsonWriteStr(json, "test2", jsonRead(json, "test3")); + jsonWriteStr(json, "test3", jsonRead(json, "test4")); + jsonWriteStr(json, "test4", jsonRead(json, "test5")); + jsonWriteStr(json, "test5", jsonRead(json, "test6")); - jsonWrite(json, "test6", GetTime() + " " + text); + jsonWriteStr(json, "test6", GetTime() + " " + text); ws.textAll(json); } @@ -345,7 +364,7 @@ void getMemoryLoad(String text) { /* -String getResetReason(uint8_t core) { + String getResetReason(uint8_t core) { int reason = rtc_get_reset_reason(core); switch (reason) { case 1 : return "Power on"; break; //Vbat power on reset @@ -365,10 +384,10 @@ String getResetReason(uint8_t core) { case 16 : return "RTC Watch dog reset digital core and rtc module"; break; default : return "NO_MEAN"; } -} + } -String EspClass::getResetReason(void) { + String EspClass::getResetReason(void) { char buff[32]; if (resetInfo.reason == REASON_DEFAULT_RST) { // normal startup by power on strcpy_P(buff, PSTR("Power on")); @@ -388,5 +407,5 @@ String EspClass::getResetReason(void) { strcpy_P(buff, PSTR("Unknown")); } return String(buff); -} + } */ diff --git a/mqtt.ino b/mqtt.ino index 61e1b97d..ac63248c 100644 --- a/mqtt.ino +++ b/mqtt.ino @@ -22,20 +22,20 @@ void MQTT_init() { server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("mqttServer")) { - jsonWrite(configSetup, "mqttServer", request->getParam("mqttServer")->value()); + jsonWriteStr(configSetup, "mqttServer", request->getParam("mqttServer")->value()); } if (request->hasArg("mqttPort")) { int port = (request->getParam("mqttPort")->value()).toInt(); - jsonWrite(configSetup, "mqttPort", port); + jsonWriteInt(configSetup, "mqttPort", port); } if (request->hasArg("mqttPrefix")) { - jsonWrite(configSetup, "mqttPrefix", request->getParam("mqttPrefix")->value()); + jsonWriteStr(configSetup, "mqttPrefix", request->getParam("mqttPrefix")->value()); } if (request->hasArg("mqttUser")) { - jsonWrite(configSetup, "mqttUser", request->getParam("mqttUser")->value()); + jsonWriteStr(configSetup, "mqttUser", request->getParam("mqttUser")->value()); } if (request->hasArg("mqttPass")) { - jsonWrite(configSetup, "mqttPass", request->getParam("mqttPass")->value()); + jsonWriteStr(configSetup, "mqttPass", request->getParam("mqttPass")->value()); } saveConfig(); start_connecting_to_mqtt = true; @@ -45,8 +45,8 @@ void MQTT_init() { server.on("/mqttCheck", HTTP_GET, [](AsyncWebServerRequest * request) { String tmp = "{}"; - jsonWrite(tmp, "title", "" + stateMQTT()); - jsonWrite(tmp, "class", "pop-up"); + jsonWriteStr(tmp, "title", "" + stateMQTT()); + jsonWriteStr(tmp, "class", "pop-up"); request->send(200, "text/text", tmp); }); } @@ -134,14 +134,12 @@ void outcoming_date() { sendAllWigets(); sendAllData(); - - if (flagLoggingAnalog) sendLogData("log.analog.txt", "loganalog"); - if (flagLoggingDallas) sendLogData("log.dallas.txt", "logdallas"); - if (flagLoggingLevel) sendLogData("log.level.txt", "loglevel"); + choose_log_date_and_send(); Serial.println("[V] Sending all date to iot manager completed"); - } + + //======================================CONFIG================================================== boolean sendMQTT(String end_of_topik, String data) { String topik = jsonRead(configSetup, "mqttPrefix") + "/" + chipID + "/" + end_of_topik; @@ -161,7 +159,7 @@ boolean sendCHART(String topik, String data) { void sendSTATUS(String topik, String state) { topik = jsonRead(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; String json_ = "{}"; - jsonWrite(json_, "status", state); + jsonWriteStr(json_, "status", state); int send_status = client.publish (topik.c_str(), json_.c_str(), false); } //======================================CONTROL================================================== @@ -172,26 +170,46 @@ void sendCONTROL(String id, String topik, String state) { //=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== void sendAllWigets() { + +#ifndef layout_in_rom + all_widgets = readFile("layout.txt", 5000); +#endif + if (all_widgets != "") { int counter = 0; String line; int psn_1 = 0; int psn_2; do { - psn_2 = all_widgets.indexOf("\r\n", psn_1); + psn_2 = all_widgets.indexOf("\r\n", psn_1); //\r\n line = all_widgets.substring(psn_1, psn_2); line.replace("\n", ""); line.replace("\r\n", ""); - //jsonWrite(line, "id", String(counter)); - //jsonWrite(line, "pageId", String(counter)); + //jsonWriteStr(line, "id", String(counter)); + //jsonWriteStr(line, "pageId", String(counter)); counter++; sendMQTT("config", line); Serial.println("[V] " + line); psn_1 = psn_2 + 1; } while (psn_2 + 2 < all_widgets.length()); getMemoryLoad("[i] after send all widgets"); +#ifndef layout_in_rom + all_widgets = ""; +#endif } } +/* +void sendAllWigets2() { + File configFile = SPIFFS.open("/layout.txt", "r"); + if (!configFile) { + return; + } + // while (str.length() != 0) { + + // configFile.readStringUntil("\r\n"); + + // } +}*/ //=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает @@ -216,32 +234,7 @@ void sendAllData() { //берет строку json и ключи превра } } -void sendLogData(String file, String topic) { - String log_date = readFile(file, 5000) + "\r\n"; - - log_date.replace("\r\n", "\n"); - log_date.replace("\r", "\n"); - - String unix_time; - String value; - - while (log_date.length() != 0) { - String tmp = selectToMarker (log_date, "\n"); - - unix_time += (selectToMarker (tmp, " ") + ","); - value += (deleteBeforeDelimiter(tmp, " ") + ","); - - log_date = deleteBeforeDelimiter(log_date, "\n"); - } - - unix_time.replace(",,", ""); - value.replace(",,", ""); - String to_send = "{\"status\":[" + value + "],\"time\": [" + unix_time + "]}"; - sendCHART(topic, to_send); - - getMemoryLoad("[i] after send log date"); -} String stateMQTT() { @@ -312,7 +305,7 @@ String stateMQTT() { /* //----------------------------------------------------------------------------------------------------------------------------------------------- - //jsonWrite(tmp, "status", "1"); + //jsonWriteStr(tmp, "status", "1"); String current_config = configJson; //{"SSDP":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} current_config.replace("{", ""); @@ -329,7 +322,7 @@ String stateMQTT() { state.replace("\"", ""); //1 //if (widget.lastIndexOf(topic) > 0) { - jsonWrite(tmp, "status", state); + jsonWriteStr(tmp, "status", state); //} current_config = deleteBeforeDelimiter(current_config, ","); } diff --git a/push_pushingbox.ino b/push_pushingbox.ino index 6e89ade6..331f4eb7 100644 --- a/push_pushingbox.ino +++ b/push_pushingbox.ino @@ -2,7 +2,7 @@ void Push_init() { server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("pushingbox_id")) { - jsonWrite(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); + jsonWriteStr(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); } saveConfig(); diff --git a/set.h b/set.h index c3be5731..cb408502 100644 --- a/set.h +++ b/set.h @@ -1,12 +1,13 @@ String firmware_version = "2.3.1"; -boolean flash_1mb = false; //----------------------------------------------------------------- String last_version; boolean start_check_version = false; //#define OTA_enable //#define MDNS_enable -//#define WS_enable +#define WS_enable + +//#define layout_in_rom #define TIME_COMPILING String(__TIME__) #define DATE_COMPILING String(__DATE__) @@ -15,9 +16,6 @@ boolean start_check_version = false; //----------------------------------------------------------------- #define analog_update_int 5000 //----------------------------------------------------------------- -#define ph_shooting_interval 500 //интервал выстрела датчика -#define ph_times_to_send 10 //после скольки выстрелов делать отправку данных -//----------------------------------------------------------------- #define temp_update_int 5000 //----------------------------------------------------------------- #define tank_level_shooting_interval 500 //интервал выстрела датчика @@ -26,7 +24,8 @@ boolean start_check_version = false; #define dhtT_update_int 10000 #define dhtH_update_int 10000 #define dht_calculation_update_int 10000 -#define statistics_update 1000 * 60 * 60 * 4 +//----------------------------------------------------------------- +#define statistics_update 1000 * 60 * 60 * 2 //----------------------------------------------------------------- @@ -80,10 +79,10 @@ AsyncEventSource events("/events"); //--------------------------------------------------------------- #include TickerScheduler ts(30); -enum {ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, LEVEL, ANALOG_, DALLAS, DHTT, DHTH, DHTC, DHTP, DHTD, STEPPER1, STEPPER2, ANALOG_LOG, LEVEL_LOG, DALLAS_LOG, CMD, TIMER_COUNTDOWN, TIMERS, TIME, STATISTICS, TEST}; +enum {ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, LEVEL, ANALOG_, DALLAS, DHTT, DHTH, DHTC, DHTP, DHTD, STEPPER1, STEPPER2, ANALOG_LOG, LEVEL_LOG, DALLAS_LOG, dhtT_LOG, dhtH_LOG, CMD, TIMER_COUNTDOWN, TIMERS, TIME, TIME_SYNC, STATISTICS, TEST}; //--------------------------------------------------------------- //ssl//#include "dependencies/WiFiClientSecure/WiFiClientSecure.h" //using older WiFiClientSecure -//#include "Ticker_for_TickerScheduler/Ticker/Ticker.h" +//#include "Ticker_for_TickerScheduler/Ticker/Ticker.h" //--------------------------------------------------------------- #include WiFiClient espClient; @@ -134,7 +133,8 @@ String order_loop; boolean flagLoggingAnalog = false; boolean flagLoggingLevel = false; boolean flagLoggingDallas = false; -boolean flagLoggingPh = false; +boolean flagLoggingdhtT = false; +boolean flagLoggingdhtH = false; const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 3600; @@ -153,3 +153,5 @@ boolean upgrade_flag = false; boolean get_url_flag = false; boolean start_connecting_to_mqtt = false; + +String test; diff --git a/test.ino b/test.ino new file mode 100644 index 00000000..c8bad15d --- /dev/null +++ b/test.ino @@ -0,0 +1,55 @@ +/* +UPD +String br = "\n\n"; + + +void info_init(){ + server.on("/info", HTTP_GET, [](AsyncWebServerRequest * request) { + String r = ESP_info_html(); + request->send(200, "text/html", ""+r+""); // отправляем ответ о выполнении + }); + sCmd.addCommand("pwr", pwr); +} + +String ESP_info_str(){ + br = "\n\n"; + return ESP_info(); +} +String ESP_info_html(){ + br = "
"; + return ESP_info(); +} + +String ESP_info(){ + + FlashMode_t ideMode = ESP.getFlashChipMode(); + String message = "hello from esp8266!"+br; + int sec = millis() / 1000; + int min = sec / 60; + int hr = min / 60; + message += "Uptime: "+String(hr)+":"+String(min % 60)+":"+String(sec % 60)+br; + message += "Vcc: " + String(ESP.getVcc() / 1024.0)+br; + message += "ESP Core Version: \t"+ ESP.getCoreVersion()+br; + message += "ESP Sdk Version: \t"+ String(ESP.getSdkVersion())+br; + message += "ESP Boot Mode: \t"+ String(ESP.getBootMode())+br; + + message += "ESP Sketch Size: \t"+ String(ESP.getSketchSize())+br; + message += "ESP Free Sketch Space: \t"+ String(ESP.getFreeSketchSpace())+br; + +#ifdef ESP32 + message += "wifi station get hostname: \t"+ String(wifi_station_get_hostname())+br; + message += "ESP min Sketch Space: \t"+ String(esp_get_minimum_free_heap_size())+br; +#endif + message += "размер свободной памяти:\t"+String(ESP.getFreeHeap())+br; + message += "chip ID:\t"+String(ESP.getChipId(),HEX)+br; + message += "flash chip ID:\t"+String(ESP.getFlashChipId(),HEX)+br; + + message += "размер флеш памяти IDE:\t"+String(ESP.getFlashChipSize())+br; + message += "размер флеш памяти SDK:\t"+String(ESP.getFlashChipRealSize())+br; + + message += "частота флеш памяти, в Гц.:\t"+String(ESP.getFlashChipSpeed())+br; + message += "Flash ide mode:\t"+ String(ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN")+br; +// message += "IP address: \t"+ WiFi.localIP()+br; + return message; +} +*/