добавил асинхронный веб сервер и веб сокеты, проверенный код

This commit is contained in:
Dmitry Borisenko
2021-12-23 00:33:45 +01:00
parent f20486517b
commit 7147e041b4
15 changed files with 201 additions and 249 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -11,3 +11,6 @@ extern FS* filesystem;
extern bool fileSystemInit(); extern bool fileSystemInit();
extern void globalVarsSync(); extern void globalVarsSync();
void saveSettingsFlashJson();
void saveParamsFlashJson();

View File

@@ -4,6 +4,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <ESP8266httpUpdate.h> #include <ESP8266httpUpdate.h>
#include <ESPAsyncWebServer.h>
#include <FS.h> #include <FS.h>
#include <TickerScheduler.h> #include <TickerScheduler.h>
@@ -15,6 +16,7 @@
//глобальные объекты классов //глобальные объекты классов
extern TickerScheduler ts; extern TickerScheduler ts;
extern AsyncWebServer server;
//глобальные переменные //глобальные переменные
extern String settingsFlashJson; extern String settingsFlashJson;

View File

@@ -1,8 +1,10 @@
//#pragma once #pragma once
//
//#include "Global.h" #include "Global.h"
//
// extern AsyncWebSocket ws;
// extern AsyncEventSource events;
// void initWS();
// void init(); void webServerInit();
void webSocketsInit();
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);

View File

@@ -3,3 +3,4 @@
#include "Global.h" #include "Global.h"
#include "Utils/Pretty.h" #include "Utils/Pretty.h"
#include "Utils/WiFiUtils.h" #include "Utils/WiFiUtils.h"
#include "WebServer.h"

View File

@@ -19,6 +19,3 @@ bool jsonWriteStr_(String& json, String name, String value);
bool jsonWriteBool_(String& json, String name, bool value); bool jsonWriteBool_(String& json, String name, bool value);
bool jsonWriteInt_(String& json, String name, int value); bool jsonWriteInt_(String& json, String name, int value);
bool jsonWriteFloat_(String& json, String name, float value); bool jsonWriteFloat_(String& json, String name, float value);
void saveConfig();
void saveStore();

View File

@@ -16,6 +16,7 @@ data_dir = data_svelte
[common_env_data] [common_env_data]
lib_deps_external = lib_deps_external =
bblanchon/ArduinoJson @6.18.0 bblanchon/ArduinoJson @6.18.0
me-no-dev/ESP Async WebServer
[env:esp8266_4mb] [env:esp8266_4mb]
build_flags = -Desp8266_4mb="esp8266_4mb" build_flags = -Desp8266_4mb="esp8266_4mb"

View File

@@ -13,3 +13,11 @@ void globalVarsSync() {
settingsFlashJson = readFile("settings.json", 4096); settingsFlashJson = readFile("settings.json", 4096);
settingsFlashJson.replace("\r\n", ""); settingsFlashJson.replace("\r\n", "");
} }
void saveSettingsFlashJson() {
writeFile(String("config.json"), settingsFlashJson);
}
void saveParamsFlashJson() {
writeFile(String("store.json"), paramsFlashJson);
}

View File

@@ -2,6 +2,7 @@
//глобальные объекты классов //глобальные объекты классов
TickerScheduler ts(MYTEST + 1); TickerScheduler ts(MYTEST + 1);
AsyncWebServer server(80);
//глобальные переменные //глобальные переменные
String settingsFlashJson = "{}"; //переменная в которой хранятся все настройки, находится в оперативной памяти только и синхронизированна с flash памятью String settingsFlashJson = "{}"; //переменная в которой хранятся все настройки, находится в оперативной памяти только и синхронизированна с flash памятью

View File

@@ -1,213 +1,147 @@
// #include "WebServer.h"
//
// AsyncWebSocket ws("/ws");
// AsyncWebSocket ws("/ws"); AsyncEventSource events("/events");
// AsyncEventSource events("/events");
// void webServerInit() {
// String login = jsonReadStr(settingsFlashJson, "weblogin");
// String pass = jsonReadStr(settingsFlashJson, "webpass");
// #ifdef ESP32
// // server.addHandler(new FSEditor(FileFS, login, pass));
// void init() { #else
// String login = jsonReadStr(settingsFlashJson, "weblogin"); // server.addHandler(new FSEditor(login, pass));
// String pass = jsonReadStr(settingsFlashJson, "webpass"); #endif
//#ifdef ESP32
// server.addHandler(new FSEditor(FileFS, login, pass)); server.serveStatic("/css/", FileFS, "/css/").setCacheControl("max-age=600");
//#else server.serveStatic("/js/", FileFS, "/js/").setCacheControl("max-age=600");
// server.addHandler(new FSEditor(login, pass)); server.serveStatic("/favicon.ico", FileFS, "/favicon.ico").setCacheControl("max-age=600");
//#endif server.serveStatic("/icon.jpeg", FileFS, "/icon.jpeg").setCacheControl("max-age=600");
// server.serveStatic("/edit", FileFS, "/edit").setCacheControl("max-age=600");
// server.serveStatic("/css/", FileFS, "/css/").setCacheControl("max-age=600");
// server.serveStatic("/js/", FileFS, "/js/").setCacheControl("max-age=600"); server.serveStatic("/", FileFS, "/").setDefaultFile("index.html").setAuthentication(login.c_str(), pass.c_str());
// server.serveStatic("/favicon.ico", FileFS, "/favicon.ico").setCacheControl("max-age=600");
// server.serveStatic("/icon.jpeg", FileFS, "/icon.jpeg").setCacheControl("max-age=600"); server.onNotFound([](AsyncWebServerRequest *request) {
// server.serveStatic("/edit", FileFS, "/edit").setCacheControl("max-age=600"); // SerialPrint("[E]", "WebServer", "not found:\n" + getRequestInfo(request));
// request->send(404);
//#ifdef svelte });
// server.serveStatic("/", FileFS, "/").setDefaultFile("index.html").setAuthentication(login.c_str(), pass.c_str());
//#else server.onFileUpload([](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) {
// server.serveStatic("/", FileFS, "/").setDefaultFile("index.htm").setAuthentication(login.c_str(), pass.c_str()); // TODO
//#endif if (!index) {
// // SerialPrint("i", "WebServer", "start upload " + filename);
// server.onNotFound([](AsyncWebServerRequest *request) { }
// SerialPrint("[E]", "WebServer", "not found:\n" + getRequestInfo(request)); if (final) {
// request->send(404); // SerialPrint("i", "WebServer", "finish upload: " + prettyBytes(index + len));
// }); }
// });
// server.onFileUpload([](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) {
// // TODO // динамические данные
// if (!index) { // server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) {
// SerialPrint("I", "WebServer", "start upload " + filename); // request->send(200, "application/json", configLiveJson);
// } //});
// if (final) { //
// SerialPrint("I", "WebServer", "finish upload: " + prettyBytes(index + len)); // server.on("/config.store.json", HTTP_GET, [](AsyncWebServerRequest *request) {
// } // request->send(200, "application/json", paramsFlashJson);
// }); //});
// //
// // динамические данные // server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest *request) {
// server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) { // request->send(200, "application/json", paramsHeapJson);
// request->send(200, "application/json", configLiveJson); //});
// }); //
// // server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest *request) {
// server.on("/config.store.json", HTTP_GET, [](AsyncWebServerRequest *request) { // request->send(200, "application/json", settingsFlashJson);
// request->send(200, "application/json", paramsFlashJson); //});
// }); //
// // server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest *request) {
// // данные не являющиеся событиями // String cmdStr = request->getParam("command")->value();
// server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest *request) { // SerialPrint("i", "WebServer", "do: " + cmdStr);
// request->send(200, "application/json", paramsHeapJson); // // loopCmdAdd(cmdStr);
// }); // request->send(200, "text/html", "OK");
// //});
// // для хранения постоянных данных
// server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest *request) { server.begin();
// request->send(200, "application/json", settingsFlashJson);
// }); SerialPrint("i", F("WEB"), F("WebServer Init"));
// }
// server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest *request) {
// String cmdStr = request->getParam("command")->value(); void webSocketsInit() {
// SerialPrint("I", "WebServer", "do: " + cmdStr); ws.onEvent(onWsEvent);
// loopCmdAdd(cmdStr); server.addHandler(&ws);
// request->send(200, "text/html", "OK"); events.onConnect([](AsyncEventSourceClient *client) {
// }); client->send("", NULL, millis(), 1000);
// });
// server.begin(); server.addHandler(&events);
// SerialPrint("i", F("WEB"), F("WebSockets Init"));
// initOta(); }
// initMDNS();
// initWS(); void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
// if (type == WS_EVT_CONNECT) {
// SerialPrint("I", F("HTTP"), F("HttpServer Init")); Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
//} client->printf("Hello Client %u :)", client->id());
// client->ping();
// void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { } else if (type == WS_EVT_DISCONNECT) {
//#ifdef WEBSOCKET_ENABLED Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id());
// if (type == WS_EVT_CONNECT) { } else if (type == WS_EVT_ERROR) {
// SerialPrint("I", F("WS"), F("CONNECTED")); Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t *)arg), (char *)data);
// Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); } else if (type == WS_EVT_PONG) {
// // client->printf(json.c_str(), client->id()); Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char *)data : "");
// // client->ping(); } else if (type == WS_EVT_DATA) {
// } else if (type == WS_EVT_DISCONNECT) { AwsFrameInfo *info = (AwsFrameInfo *)arg;
// Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); String msg = "";
// } else if (type == WS_EVT_ERROR) { if (info->final && info->index == 0 && info->len == len) {
// Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t *)arg), (char *)data); // the whole message is in a single frame and we got all of it's data
// } else if (type == WS_EVT_PONG) { Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len);
// Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char *)data : "");
// } else if (type == WS_EVT_DATA) { if (info->opcode == WS_TEXT) {
// AwsFrameInfo *info = (AwsFrameInfo *)arg; for (size_t i = 0; i < info->len; i++) {
// String msg = ""; msg += (char)data[i];
// if (info->final && info->index == 0 && info->len == len) { }
// // the whole message is in a single frame and we got all of it's data } else {
// Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len); char buff[3];
// for (size_t i = 0; i < info->len; i++) {
// if (info->opcode == WS_TEXT) { sprintf(buff, "%02x ", (uint8_t)data[i]);
// for (size_t i = 0; i < info->len; i++) { msg += buff;
// msg += (char)data[i]; }
// } }
// } else { Serial.printf("%s\n", msg.c_str());
// char buff[3];
// for (size_t i = 0; i < info->len; i++) { if (info->opcode == WS_TEXT)
// sprintf(buff, "%02x ", (uint8_t)data[i]); client->text("I got your text message");
// msg += buff; else
// } client->binary("I got your binary message");
// } } else {
// Serial.printf("%s\n", msg.c_str()); // message is comprised of multiple frames or the frame is split into multiple packets
// if (info->index == 0) {
// if (msg.startsWith("HELLO")) { if (info->num == 0)
// SerialPrint("I", F("WS"), F("Full update")); Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary");
// // publishWidgetsWS(); Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len);
// // publishStateWS(); }
// // choose_log_date_and_send(); // функцию выгрузки архива с графиком я не сделал. Забираю при выгрузке по MQTT
// } Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len);
//
// if (info->opcode == WS_TEXT) if (info->opcode == WS_TEXT) {
// client->text("{}"); for (size_t i = 0; i < len; i++) {
// else msg += (char)data[i];
// client->binary("{}"); }
// } else { } else {
// // message is comprised of multiple frames or the frame is split into multiple packets char buff[3];
// if (info->index == 0) { for (size_t i = 0; i < len; i++) {
// if (info->num == 0) sprintf(buff, "%02x ", (uint8_t)data[i]);
// Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); msg += buff;
// Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); }
// } }
// Serial.printf("%s\n", msg.c_str());
// Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len);
// if ((info->index + len) == info->len) {
// if (info->opcode == WS_TEXT) { Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
// for (size_t i = 0; i < len; i++) { if (info->final) {
// msg += (char)data[i]; Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary");
// } if (info->message_opcode == WS_TEXT)
// } else { client->text("I got your text message");
// char buff[3]; else
// for (size_t i = 0; i < len; i++) { client->binary("I got your binary message");
// sprintf(buff, "%02x ", (uint8_t)data[i]); }
// msg += buff; }
// } }
// } }
// Serial.printf("%s\n", msg.c_str()); }
//
// if ((info->index + len) == info->len) {
// Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
// if (info->final) {
// Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary");
// if (info->message_opcode == WS_TEXT)
// client->text("I got your text message");
// else
// client->binary("I got your binary message");
// }
// }
// }
// }
//#endif
// ;
//}
//
// void initMDNS() {
//#ifdef MDNS_ENABLED
// MDNS.addService("http", "tcp", 80);
// // TODO Add Adduino OTA
//#endif
// ;
//}
//
// void initOta() {
//#ifdef OTA_UPDATES_ENABLED
// ArduinoOTA.onStart([]() {
// events.send("Update Start", "ota");
// });
// ArduinoOTA.onEnd([]() {
// events.send("Update End", "ota");
// });
// ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
// char p[32];
// sprintf(p, "Progress: %u%%\n", (progress / (total / 100)));
// events.send(p, "ota");
// });
// ArduinoOTA.onError([](ota_error_t error) {
// if (error == OTA_AUTH_ERROR)
// events.send("Auth Failed", "ota");
// else if (error == OTA_BEGIN_ERROR)
// events.send("Begin Failed", "ota");
// else if (error == OTA_CONNECT_ERROR)
// events.send("Connect Failed", "ota");
// else if (error == OTA_RECEIVE_ERROR)
// events.send("Recieve Failed", "ota");
// else if (error == OTA_END_ERROR)
// events.send("End Failed", "ota");
// });
// ArduinoOTA.setHostname(hostName);
// ArduinoOTA.begin();
//#endif
// ;
//}
//
// void initWS() {
//#ifdef WEBSOCKET_ENABLED
// ws.onEvent(onWsEvent);
// server.addHandler(&ws);
// events.onConnect([](AsyncEventSourceClient *client) {
// client->send("", NULL, millis(), 1000);
// });
// server.addHandler(&events);
//#endif
//}

View File

@@ -12,11 +12,20 @@ void setup() {
//синхронизация глобальных переменных с flash //синхронизация глобальных переменных с flash
globalVarsSync(); globalVarsSync();
//инициализация асинхронного веб сервера
webServerInit();
//инициализация веб сокетов асинхронного веб сервера
webSocketsInit();
//подключаемся к роутеру //подключаемся к роутеру
routerConnect(); routerConnect();
//выводим остаток оперативной памяти после старта //выводим остаток оперативной памяти после старта
// 22.12.21 пустой код без wifi остаток = 50.28 kB // 22.12.21 пустой код без wifi остаток = 50.28 kB
// 22.12.21 запустил wifi остаток = 48.59 kB
// 22.12.21 добавил асинхронный веб сервер = 38.36 kB
// 22.12.21 добавил web sockets = 37.63 kB
SerialPrint(F("i"), F("HEAP"), prettyBytes(ESP.getFreeHeap())); SerialPrint(F("i"), F("HEAP"), prettyBytes(ESP.getFreeHeap()));
} }

View File

@@ -166,11 +166,5 @@ bool jsonWriteFloat_(String& json, String key, float value) {
serializeJson(doc, json); serializeJson(doc, json);
return ret; return ret;
} }
//=================================================================================
void saveConfig() {
writeFile(String("config.json"), settingsFlashJson);
}
void saveStore() { //=================================================================================
writeFile(String("store.json"), paramsFlashJson);
}

View File

@@ -124,9 +124,9 @@ void breakEpochToTime(unsigned long epoch, Time_t& tm) {
// prevTime = timenow; // prevTime = timenow;
// jsonWriteStr(configLiveJson, "timenow", timenow); // jsonWriteStr(configLiveJson, "timenow", timenow);
// eventGen2("timenow", timenow); // eventGen2("timenow", timenow);
// SerialPrint("I", F("NTP"), timenow); // SerialPrint("i", F("NTP"), timenow);
// } // }
// }, // },
// nullptr, true); // nullptr, true);
// SerialPrint("I", F("NTP"), F("Handle time init")); // SerialPrint("i", F("NTP"), F("Handle time init"));
//} //}

View File

@@ -19,8 +19,8 @@ void routerConnect() {
#else #else
WiFi.setOutputPower(20.5); WiFi.setOutputPower(20.5);
#endif #endif
SerialPrint("I", "WIFI", "ssid: " + _ssid); SerialPrint("i", "WIFI", "ssid: " + _ssid);
SerialPrint("I", "WIFI", "pass: " + _password); SerialPrint("i", "WIFI", "pass: " + _password);
} }
while (--tries && WiFi.status() != WL_CONNECTED) { while (--tries && WiFi.status() != WL_CONNECTED) {
@@ -38,16 +38,16 @@ void routerConnect() {
startAPMode(); startAPMode();
} else { } else {
Serial.println(""); Serial.println("");
SerialPrint("I", "WIFI", "http://" + WiFi.localIP().toString()); SerialPrint("i", "WIFI", "http://" + WiFi.localIP().toString());
jsonWriteStr(settingsFlashJson, "ip", WiFi.localIP().toString()); jsonWriteStr(settingsFlashJson, "ip", WiFi.localIP().toString());
//mqttInit(); //mqttInit();
} }
SerialPrint("I", F("WIFI"), F("Network Init")); SerialPrint("i", F("WIFI"), F("Network Init"));
} }
bool startAPMode() { bool startAPMode() {
SerialPrint("I", "WIFI", "AP Mode"); SerialPrint("i", "WIFI", "AP Mode");
WiFi.disconnect(); WiFi.disconnect();
WiFi.mode(WIFI_AP); WiFi.mode(WIFI_AP);
@@ -58,7 +58,7 @@ bool startAPMode() {
WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str());
IPAddress myIP = WiFi.softAPIP(); IPAddress myIP = WiFi.softAPIP();
SerialPrint("I", "WIFI", "AP IP: " + myIP.toString()); SerialPrint("i", "WIFI", "AP IP: " + myIP.toString());
jsonWriteStr(settingsFlashJson, "ip", myIP.toString()); jsonWriteStr(settingsFlashJson, "ip", myIP.toString());
// if (jsonReadInt(paramsHeapJson, "pass_status") != 1) { // if (jsonReadInt(paramsHeapJson, "pass_status") != 1) {
@@ -66,7 +66,7 @@ bool startAPMode() {
WIFI_SCAN, 10 * 1000, [&](void*) { WIFI_SCAN, 10 * 1000, [&](void*) {
String sta_ssid = jsonReadStr(settingsFlashJson, "routerssid"); String sta_ssid = jsonReadStr(settingsFlashJson, "routerssid");
SerialPrint("I", "WIFI", "scanning for " + sta_ssid); SerialPrint("i", "WIFI", "scanning for " + sta_ssid);
if (RouterFind(sta_ssid)) { if (RouterFind(sta_ssid)) {
ts.remove(WIFI_SCAN); ts.remove(WIFI_SCAN);
@@ -82,19 +82,19 @@ bool startAPMode() {
boolean RouterFind(String ssid) { boolean RouterFind(String ssid) {
bool res = false; bool res = false;
int n = WiFi.scanComplete(); int n = WiFi.scanComplete();
SerialPrint("I", "WIFI", "scan result: " + String(n, DEC)); SerialPrint("i", "WIFI", "scan result: " + String(n, DEC));
if (n == -2) { //Сканирование не было запущено, запускаем if (n == -2) { //Сканирование не было запущено, запускаем
SerialPrint("I", "WIFI", "start scanning"); SerialPrint("i", "WIFI", "start scanning");
WiFi.scanNetworks(true, false); // async, show_hidden WiFi.scanNetworks(true, false); // async, show_hidden
} }
else if (n == -1) { //Сканирование все еще выполняется else if (n == -1) { //Сканирование все еще выполняется
SerialPrint("I", "WIFI", "scanning in progress"); SerialPrint("i", "WIFI", "scanning in progress");
} }
else if (n == 0) { //ни одна сеть не найдена else if (n == 0) { //ни одна сеть не найдена
SerialPrint("I", "WIFI", "no networks found"); SerialPrint("i", "WIFI", "no networks found");
WiFi.scanNetworks(true, false); WiFi.scanNetworks(true, false);
} }
@@ -103,7 +103,7 @@ boolean RouterFind(String ssid) {
if (WiFi.SSID(i) == ssid) { if (WiFi.SSID(i) == ssid) {
res = true; res = true;
} }
SerialPrint("I", "WIFI", (res ? "*" : "") + String(i, DEC) + ") " + WiFi.SSID(i)); SerialPrint("i", "WIFI", (res ? "*" : "") + String(i, DEC) + ") " + WiFi.SSID(i));
} }
} }
WiFi.scanDelete(); WiFi.scanDelete();
@@ -138,7 +138,7 @@ uint8_t RSSIquality() {
void wifiSignalInit() { void wifiSignalInit() {
ts.add( ts.add(
SYGNAL, 1000 * 60, [&](void*) { SYGNAL, 1000 * 60, [&](void*) {
//SerialPrint("I", "System", printMemoryStatus()); //SerialPrint("i", "System", printMemoryStatus());
//getFSInfo(); //getFSInfo();