From b930066d7a95a3dd4dc35cc15f95db0394e4bf59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChl?= <31169771+Blueforcer@users.noreply.github.com> Date: Thu, 11 May 2023 22:32:42 +0200 Subject: [PATCH] V0.62 - Adds AWTRIX Flows link to webinterface - Inidkator blinking is now set by a given blinking-interval - Adds LookingEyes app as native app, wich is well known from Awtrix2 - Allows to set a longer Apptime wich is now set as seconds instead of milliseconds. closes #106 - Limits battery percentage. closes #120 - Disables Artnet reading in AP-Mode. closes #116 - Add another transistion check. closes #114 - increase jsonbuffer for drawing commands. closes #112 --- docs/api.md | 7 +- lib/webserver/{src => }/edit_htm.h | 0 lib/webserver/{src => }/esp-fs-webserver.cpp | 1840 ++++++++--------- lib/webserver/{src => }/esp-fs-webserver.h | 694 +++---- lib/webserver/{src => }/linked_list.h | 324 +-- lib/webserver/setup-ui/data/app.js | 484 ----- lib/webserver/setup-ui/data/build/min/all.htm | 132 -- .../setup-ui/data/build/min/all.htm.gz | Bin 8405 -> 0 bytes lib/webserver/setup-ui/data/build/min/app.js | 1 - .../setup-ui/data/build/min/style.css | 1 - lib/webserver/setup-ui/data/build/minify.js | 71 - .../setup-ui/data/build/package-lock.json | 1524 -------------- .../setup-ui/data/build/package.json | 19 - lib/webserver/setup-ui/data/build/readme.md | 5 - .../setup-ui/data/build/stringConverter.js | 48 - lib/webserver/setup-ui/data/package-lock.json | 6 - lib/webserver/setup-ui/data/setup.htm | 132 -- lib/webserver/setup-ui/data/style.css | 597 ------ lib/webserver/setup-ui/extras.zip | Bin 8449 -> 0 bytes lib/webserver/setup-ui/extras/edit.htm | 307 --- lib/webserver/setup-ui/extras/edit.htm.gz | Bin 6553 -> 0 bytes lib/webserver/setup-ui/extras/edit_htm.h | 4 - .../setup-ui/extras/feathericons.png | Bin 1558 -> 0 bytes .../setup-ui/extras/package-lock.json | 202 -- lib/webserver/setup-ui/extras/package.json | 5 - lib/webserver/setup-ui/extras/reduce_index.sh | 59 - lib/webserver/setup-ui/readme.md | 6 - .../{setup-ui/data/build => }/setup_htm.h | 531 ++--- lib/webserver/src/setup.htm | 110 - lib/webserver/src/setup_htm.h | 529 ----- src/Apps.h | 75 +- src/DisplayManager.cpp | 83 +- src/DisplayManager.h | 6 +- src/Globals.cpp | 5 +- src/Globals.h | 1 + src/LookingEyes.h | 21 + src/MQTTManager.cpp | 4 +- src/MatrixDisplayUi.cpp | 14 +- src/MatrixDisplayUi.h | 16 +- src/MenuManager.cpp | 29 +- src/PeripheryManager.cpp | 2 +- src/icons.h | 1 + src/main.cpp | 4 +- 43 files changed, 1893 insertions(+), 6006 deletions(-) rename lib/webserver/{src => }/edit_htm.h (100%) rename lib/webserver/{src => }/esp-fs-webserver.cpp (96%) rename lib/webserver/{src => }/esp-fs-webserver.h (96%) rename lib/webserver/{src => }/linked_list.h (97%) delete mode 100644 lib/webserver/setup-ui/data/app.js delete mode 100644 lib/webserver/setup-ui/data/build/min/all.htm delete mode 100644 lib/webserver/setup-ui/data/build/min/all.htm.gz delete mode 100644 lib/webserver/setup-ui/data/build/min/app.js delete mode 100644 lib/webserver/setup-ui/data/build/min/style.css delete mode 100644 lib/webserver/setup-ui/data/build/minify.js delete mode 100644 lib/webserver/setup-ui/data/build/package-lock.json delete mode 100644 lib/webserver/setup-ui/data/build/package.json delete mode 100644 lib/webserver/setup-ui/data/build/readme.md delete mode 100644 lib/webserver/setup-ui/data/build/stringConverter.js delete mode 100644 lib/webserver/setup-ui/data/package-lock.json delete mode 100644 lib/webserver/setup-ui/data/setup.htm delete mode 100644 lib/webserver/setup-ui/data/style.css delete mode 100644 lib/webserver/setup-ui/extras.zip delete mode 100644 lib/webserver/setup-ui/extras/edit.htm delete mode 100644 lib/webserver/setup-ui/extras/edit.htm.gz delete mode 100644 lib/webserver/setup-ui/extras/edit_htm.h delete mode 100644 lib/webserver/setup-ui/extras/feathericons.png delete mode 100644 lib/webserver/setup-ui/extras/package-lock.json delete mode 100644 lib/webserver/setup-ui/extras/package.json delete mode 100644 lib/webserver/setup-ui/extras/reduce_index.sh delete mode 100644 lib/webserver/setup-ui/readme.md rename lib/webserver/{setup-ui/data/build => }/setup_htm.h (52%) delete mode 100644 lib/webserver/src/setup.htm delete mode 100644 lib/webserver/src/setup_htm.h create mode 100644 src/LookingEyes.h diff --git a/docs/api.md b/docs/api.md index 63115c1a..a6e559cb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -54,7 +54,7 @@ A colored indicator is like a small notification sign wich will be shown on the Instead of a RGB array you can also sent HEX color strings like `{"color":"#32a852"}` Send the color black `{"color":[0,0,0]}` or `{"color":"0"}` or a empty payload/body to hide the indicators. -Optionally you can make the indicator blinking by adding the key `"blink":true/false`. +Optionally you can make the indicator blinking by adding the key `"blink"` with a value of the blinking interval in milliseconds. ## Custom Apps and Notifications With AWTRIX Light, you can create custom apps or notifications to display your own text and icons. @@ -214,8 +214,9 @@ Built-in app names are: - `date` - `temp` - `hum` -- `bat` - +- `bat` +- `eyes` + For custom apps, use the name you set in the topic or http request header. In MQTT for example, if `[PREFIX]/custom/test` is your topic, then `test` is the name. diff --git a/lib/webserver/src/edit_htm.h b/lib/webserver/edit_htm.h similarity index 100% rename from lib/webserver/src/edit_htm.h rename to lib/webserver/edit_htm.h diff --git a/lib/webserver/src/esp-fs-webserver.cpp b/lib/webserver/esp-fs-webserver.cpp similarity index 96% rename from lib/webserver/src/esp-fs-webserver.cpp rename to lib/webserver/esp-fs-webserver.cpp index 212b111a..6dc4a43c 100644 --- a/lib/webserver/src/esp-fs-webserver.cpp +++ b/lib/webserver/esp-fs-webserver.cpp @@ -1,921 +1,921 @@ -#include "esp-fs-webserver.h" - -FSWebServer::FSWebServer(fs::FS &fs, WebServerClass &server) -{ - m_filesystem = &fs; - webserver = &server; - m_basePath[0] = '\0'; -} - -WebServerClass *FSWebServer::getRequest() -{ - return webserver; -} - -void FSWebServer::run() -{ - webserver->handleClient(); - if (m_apmode) - m_dnsServer.processNextRequest(); -} - -void FSWebServer::addHandler(const Uri &uri, HTTPMethod method, WebServerClass::THandlerFunction fn) -{ - webserver->on(uri, method, fn); -} - -void FSWebServer::onNotFound(WebServerClass::THandlerFunction fn) -{ - webserver->onNotFound(fn); -} - -void FSWebServer::addHandler(const Uri &uri, WebServerClass::THandlerFunction handler) -{ - webserver->on(uri, HTTP_ANY, handler); -} - -// List all files saved in the selected filesystem -bool FSWebServer::checkDir(char *dirname, uint8_t levels) -{ - if (dirname[0] != '/') - dirname[0] = '/'; - File root = m_filesystem->open(dirname, "r"); - if (!root) - { - DebugPrintln("- failed to open directory\n"); - return false; - } - if (!root.isDirectory()) - { - DebugPrintln(" - not a directory\n"); - return false; - } - File file = root.openNextFile(); - while (file) - { - if (file.isDirectory()) - { - char dir[16]; - strcpy(dir, "/"); - strcat(dir, file.name()); - DebugPrintf("DIR : %s\n", dir); - checkDir(dir, levels - 1); - } - else - { - DebugPrintf(" FILE: %s\tSIZE: %d\n", file.name(), file.size()); - } - file = root.openNextFile(); - } - return true; -} - -bool FSWebServer::begin(const char *path) -{ - DebugPrintln("\nList the files of webserver: "); - if (path != nullptr) - strcpy(m_basePath, path); - - m_fsOK = checkDir(m_basePath, 2); - -#ifdef INCLUDE_EDIT_HTM - webserver->on("/status", HTTP_GET, std::bind(&FSWebServer::handleStatus, this)); - webserver->on("/list", HTTP_GET, std::bind(&FSWebServer::handleFileList, this)); - webserver->on("/edit", HTTP_GET, std::bind(&FSWebServer::handleGetEdit, this)); - webserver->on("/edit", HTTP_PUT, std::bind(&FSWebServer::handleFileCreate, this)); - webserver->on("/edit", HTTP_DELETE, std::bind(&FSWebServer::handleFileDelete, this)); -#endif - webserver->onNotFound(std::bind(&FSWebServer::handleRequest, this)); - webserver->on("/favicon.ico", HTTP_GET, std::bind(&FSWebServer::replyOK, this)); - webserver->on("/", HTTP_GET, std::bind(&FSWebServer::handleIndex, this)); -#ifdef INCLUDE_SETUP_HTM - webserver->on("/setup", HTTP_GET, std::bind(&FSWebServer::handleSetup, this)); -#endif - webserver->on("/scan", HTTP_GET, std::bind(&FSWebServer::handleScanNetworks, this)); - webserver->on("/connect", HTTP_POST, std::bind(&FSWebServer::doWifiConnection, this)); - webserver->on("/restart", HTTP_GET, std::bind(&FSWebServer::doRestart, this)); - webserver->on("/ipaddress", HTTP_GET, std::bind(&FSWebServer::getIpAddress, this)); - - // Captive Portal redirect - webserver->on("/redirect", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); - // Windows - webserver->on("/connecttest.txt", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); - // Apple - webserver->on("/hotspot-detect.html", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); - // Android - webserver->on("/generate_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); - webserver->on("/gen_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); - - // Upload file - // - first callback is called after the request has ended with all parsed arguments - // - second callback handles file upload at that location - webserver->on("/edit", HTTP_POST, std::bind(&FSWebServer::replyOK, this), std::bind(&FSWebServer::handleFileUpload, this)); - - // OTA update via webbrowser - m_httpUpdater.setup(webserver); - - - webserver->enableCORS(true); - - webserver->setContentLength(1024); - webserver->begin(); - - return true; -} - -void FSWebServer::setCaptiveWebage(const char *url) -{ - m_apWebpage = (char *)realloc(m_apWebpage, sizeof(url)); - strcpy(m_apWebpage, url); -} - -IPAddress FSWebServer::setAPmode(const char *ssid, const char *psk) -{ - m_apmode = true; - WiFi.mode(WIFI_AP_STA); - WiFi.persistent(false); - WiFi.softAP(ssid, psk); - /* Setup the DNS server redirecting all the domains to the apIP */ - m_dnsServer.setErrorReplyCode(DNSReplyCode::NoError); - m_dnsServer.start(53, "*", WiFi.softAPIP()); - return WiFi.softAPIP(); -} - -IPAddress FSWebServer::startWiFi(uint32_t timeout, const char *apSSID, const char *apPsw) -{ - IPAddress ip; - m_timeout = timeout; - WiFi.mode(WIFI_STA); - - const char *_ssid; - const char *_pass; - - wifi_config_t conf; - esp_wifi_get_config(WIFI_IF_STA, &conf); - - _ssid = reinterpret_cast(conf.sta.ssid); - _pass = reinterpret_cast(conf.sta.password); - - if (strlen(_ssid) && strlen(_pass)) - { - WiFi.begin(_ssid, _pass); - Serial.print(F("Connecting to ")); - Serial.println(_ssid); - - uint32_t startTime = millis(); - while (WiFi.status() != WL_CONNECTED) - { - delay(300); - Serial.print("."); - if (WiFi.status() == WL_CONNECTED) - { - WiFi.setAutoReconnect(true); - WiFi.persistent(true); - ip = WiFi.localIP(); - return ip; - } - // If no connection after a while go in Access Point mode - if (millis() - startTime > m_timeout) - break; - } - } - - if (apSSID != nullptr && apPsw != nullptr) - setAPmode(apSSID, apPsw); - else - setAPmode("ESP_AP", "123456789"); - - WiFi.begin(); - ip = WiFi.softAPIP(); - Serial.print(F("\nAP mode.\nServer IP address: ")); - Serial.println(ip); - Serial.println(); - return ip; -} - -//////////////////////////////// WiFi ///////////////////////////////////////// - -/** - * Redirect to captive portal if we got a request for another domain. - */ -bool FSWebServer::captivePortal() -{ - IPAddress ip = webserver->client().localIP(); - char serverLoc[sizeof("https:://255.255.255.255/") + sizeof(m_apWebpage) + 1]; - snprintf(serverLoc, sizeof(serverLoc), "http://%d.%d.%d.%d%s", ip[0], ip[1], ip[2], ip[3], m_apWebpage); - - // redirect if hostheader not server ip, prevent redirect loops - if (strcmp(serverLoc, webserver->hostHeader().c_str())) - { - webserver->sendHeader(F("Location"), serverLoc, true); - webserver->send(302, F("text/html"), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. - webserver->client().stop(); // Stop is needed because we sent no content length - return true; - } - return false; -} - -void FSWebServer::handleRequest() -{ - if (!m_fsOK) - { - replyToCLient(ERROR, PSTR(FS_INIT_ERROR)); - return; - } -#if defined(ESP32) - String _url = WebServer::urlDecode(webserver->uri()); -#elif defined(ESP8266) - String _url = ESP8266WebServer::urlDecode(webserver->uri()); -#endif - // First try to find and return the requested file from the filesystem, - // and if it fails, return a 404 page with debug information - // Serial.print("urlDecode: "); - // Serial.println(_url); - if (handleFileRead(_url)) - return; - else - replyToCLient(NOT_FOUND, PSTR(FILE_NOT_FOUND)); -} - -void FSWebServer::getIpAddress() -{ - webserver->send(200, "text/json", WiFi.localIP().toString()); -} - -void FSWebServer::doRestart() -{ - Serial.println("RESTART"); - webserver->send(200, "text/json", "Going to restart ESP"); - delay(500); - ESP.restart(); -} - -void FSWebServer::doWifiConnection() -{ - String ssid, pass; - bool persistent = true; - WiFi.mode(WIFI_AP_STA); - - if (webserver->hasArg("ssid")) - { - ssid = webserver->arg("ssid"); - } - - if (webserver->hasArg("password")) - { - pass = webserver->arg("password"); - } - - if (webserver->hasArg("persistent")) - { - String pers = webserver->arg("persistent"); - if (pers.equals("false")) - { - persistent = false; - } - } - - if (WiFi.status() == WL_CONNECTED) - { - - IPAddress ip = WiFi.localIP(); - String resp = "ESP is currently connected to a WiFi network.

" - "Actual connection will be closed and a new attempt will be done with "; - resp += ssid; - resp += " WiFi network."; - webserver->send(200, "text/plain", resp); - - delay(500); - Serial.println("Disconnect from current WiFi network"); - WiFi.disconnect(); - } - - if (ssid.length() && pass.length()) - { - // Try to connect to new ssid - Serial.print("\nConnecting to "); - Serial.println(ssid); - WiFi.begin(ssid.c_str(), pass.c_str()); - - uint32_t beginTime = millis(); - while (WiFi.status() != WL_CONNECTED) - { - delay(300); - Serial.print("*.*"); - if (millis() - beginTime > m_timeout) - break; - } - // reply to client - if (WiFi.status() == WL_CONNECTED) - { - // WiFi.softAPdisconnect(); - IPAddress ip = WiFi.localIP(); - Serial.print("\nConnected to Wifi! IP address: "); - Serial.println(ip); - webserver->send(200, "text/plain", ip.toString()); - m_apmode = false; - delay(500); - ESP.restart(); - // Store current WiFi configuration in flash - if (persistent) - { -#if defined(ESP8266) - struct station_config stationConf; - wifi_station_get_config_default(&stationConf); - // Clear previuos configuration - memset(&stationConf, 0, sizeof(stationConf)); - os_memcpy(&stationConf.ssid, ssid.c_str(), ssid.length()); - os_memcpy(&stationConf.password, pass.c_str(), pass.length()); - wifi_set_opmode(STATION_MODE); - wifi_station_set_config(&stationConf); -#elif defined(ESP32) - wifi_config_t stationConf; - esp_wifi_get_config(WIFI_IF_STA, &stationConf); - // Clear previuos configuration - memset(&stationConf, 0, sizeof(stationConf)); - memcpy(&stationConf.sta.ssid, ssid.c_str(), ssid.length()); - memcpy(&stationConf.sta.password, pass.c_str(), pass.length()); - esp_wifi_set_config(WIFI_IF_STA, &stationConf); -#endif - } - else - { -#if defined(ESP8266) - struct station_config stationConf; - wifi_station_get_config_default(&stationConf); - // Clear previuos configuration - memset(&stationConf, 0, sizeof(stationConf)); - wifi_station_set_config(&stationConf); -#elif defined(ESP32) - wifi_config_t stationConf; - esp_wifi_get_config(WIFI_IF_STA, &stationConf); - // Clear previuos configuration - memset(&stationConf, 0, sizeof(stationConf)); - esp_wifi_set_config(WIFI_IF_STA, &stationConf); -#endif - } - } - else - webserver->send(500, "text/plain", "Connection error, maybe the password is wrong?"); - } - webserver->send(500, "text/plain", "Wrong credentials provided"); -} - -void FSWebServer::setCrossOrigin() -{ - webserver->sendHeader(F("Access-Control-Allow-Origin"), F("*")); - webserver->sendHeader(F("Access-Control-Max-Age"), F("600")); - webserver->sendHeader(F("Access-Control-Allow-Methods"), F("PUT,POST,GET,OPTIONS")); - webserver->sendHeader(F("Access-Control-Allow-Headers"), F("*")); -}; - -void FSWebServer::handleScanNetworks() -{ - String jsonList = "["; - DebugPrint("Scanning WiFi networks..."); - int n = WiFi.scanNetworks(); - DebugPrintln(" complete."); - if (n == 0) - { - DebugPrintln("no networks found"); - webserver->send(200, "text/json", "[]"); - return; - } - else - { - DebugPrint(n); - DebugPrintln(" networks found:"); - - for (int i = 0; i < n; ++i) - { - String ssid = WiFi.SSID(i); - int rssi = WiFi.RSSI(i); -#if defined(ESP8266) - String security = WiFi.encryptionType(i) == AUTH_OPEN ? "none" : "enabled"; -#elif defined(ESP32) - String security = WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "none" : "enabled"; -#endif - jsonList += "{\"ssid\":\""; - jsonList += ssid; - jsonList += "\",\"strength\":\""; - jsonList += rssi; - jsonList += "\",\"security\":"; - jsonList += security == "none" ? "false" : "true"; - jsonList += ssid.equals(WiFi.SSID()) ? ",\"selected\": true" : ""; - jsonList += i < n - 1 ? "}," : "}"; - } - jsonList += "]"; - } - webserver->send(200, "text/json", jsonList); - DebugPrintln(jsonList); -} - -#ifdef INCLUDE_SETUP_HTM - -void FSWebServer::addDropdownList(const char *label, const char **array, size_t size) -{ - File file = m_filesystem->open("/config.json", "r"); - int sz = file.size() * 1.33; - int docSize = max(sz, 2048); - DynamicJsonDocument doc((size_t)docSize); - if (file) - { - // If file is present, load actual configuration - DeserializationError error = deserializeJson(doc, file); - if (error) - { - DebugPrintln(F("Failed to deserialize file, may be corrupted")); - DebugPrintln(error.c_str()); - file.close(); - return; - } - file.close(); - } - else - { - DebugPrintln(F("File not found, will be created new configuration file")); - } - - numOptions++; - - // If key is present in json, we don't need to create it. - if (doc.containsKey(label)) - return; - - JsonObject obj = doc.createNestedObject(label); - obj["selected"] = array[0]; // first element selected as default - JsonArray arr = obj.createNestedArray("values"); - for (int i = 0; i < size; i++) - { - arr.add(array[i]); - } - - file = m_filesystem->open("/config.json", "w"); - if (serializeJsonPretty(doc, file) == 0) - { - DebugPrintln(F("Failed to write to file")); - } - file.close(); -} - -void FSWebServer::removeWhiteSpaces(String &str) -{ - const char noChars[] = {'\n', '\r', '\t'}; - int pos = -1; - // Remove non printable characters - for (int i = 0; i < sizeof(noChars); i++) - { - pos = str.indexOf(noChars[i]); - while (pos > -1) - { - str.replace(String(noChars[i]), ""); - pos = str.indexOf(noChars[i]); - } - } - // Remove doubles spaces - pos = str.indexOf(" "); - while (pos > -1) - { - str.replace(" ", " "); - pos = str.indexOf(" "); - } -} - -void FSWebServer::handleSetup() -{ - webserver->sendHeader(PSTR("Content-Encoding"), "gzip"); - webserver->send_P(200, "text/html", SETUP_HTML, SETUP_HTML_SIZE); -} -#endif - -void FSWebServer::handleIndex() -{ - if (m_filesystem->exists("/index.htm")) - { - handleFileRead("/index.htm"); - } - else if (m_filesystem->exists("/index.html")) - { - handleFileRead("/index.html"); - } -#ifdef INCLUDE_SETUP_HTM - else - { - handleSetup(); - } -#endif -} - -/* - Read the given file from the filesystem and stream it back to the client -*/ -bool FSWebServer::handleFileRead(const String &uri) -{ - String path = m_basePath; - path = uri; - - DebugPrintln("handleFileRead: " + path); - if (path.endsWith("/")) - { - path += "index.htm"; - } - String pathWithGz = path + ".gz"; - - if (m_filesystem->exists(pathWithGz) || m_filesystem->exists(path)) - { - if (m_filesystem->exists(pathWithGz)) - { - path += ".gz"; - } - const char *contentType = getContentType(path.c_str()); - File file = m_filesystem->open(path, "r"); - if (webserver->streamFile(file, contentType) != file.size()) - { - DebugPrintln(PSTR("Sent less data than expected!")); - // webserver->stop(); - } - file.close(); - return true; - } - return false; -} - -/* - Handle a file upload request -*/ -void FSWebServer::handleFileUpload() -{ - if (webserver->uri() != "/edit") - { - return; - } - HTTPUpload &upload = webserver->upload(); - if (upload.status == UPLOAD_FILE_START) - { - String filename = upload.filename; - String result; - // Make sure paths always start with "/" - if (!filename.startsWith("/")) - { - filename = "/" + filename; - } - checkForUnsupportedPath(filename, result); - if (result.length() > 0) - { - replyToCLient(ERROR, PSTR("INVALID FILENAME")); - return; - } - - DebugPrintf_P(PSTR("handleFileUpload Name: %s\n"), filename.c_str()); - m_uploadFile = m_filesystem->open(filename, "w"); - if (!m_uploadFile) - { - replyToCLient(ERROR, PSTR("CREATE FAILED")); - return; - } - DebugPrintf_P(PSTR("Upload: START, filename: %s\n"), filename.c_str()); - } - else if (upload.status == UPLOAD_FILE_WRITE) - { - if (m_uploadFile) - { - size_t bytesWritten = m_uploadFile.write(upload.buf, upload.currentSize); - if (bytesWritten != upload.currentSize) - { - replyToCLient(ERROR, PSTR("WRITE FAILED")); - return; - } - } - DebugPrintf_P(PSTR("Upload: WRITE, Bytes: %d\n"), upload.currentSize); - } - else if (upload.status == UPLOAD_FILE_END) - { - if (m_uploadFile) - { - m_uploadFile.close(); - } - DebugPrintf_P(PSTR("Upload: END, Size: %d\n"), upload.totalSize); - } -} - -void FSWebServer::replyOK() -{ - replyToCLient(OK, ""); -} - -void FSWebServer::replyToCLient(int msg_type = 0, const char *msg = "") -{ - //webserver->sendHeader("Access-Control-Allow-Origin", "*"); - switch (msg_type) - { - case OK: - webserver->send(200, FPSTR(TEXT_PLAIN), ""); - break; - case CUSTOM: - webserver->send(200, FPSTR(TEXT_PLAIN), msg); - break; - case NOT_FOUND: - webserver->send(404, FPSTR(TEXT_PLAIN), msg); - break; - case BAD_REQUEST: - webserver->send(400, FPSTR(TEXT_PLAIN), msg); - break; - case ERROR: - webserver->send(500, FPSTR(TEXT_PLAIN), msg); - break; - } -} - -/* - Checks filename for character combinations that are not supported by FSBrowser (alhtough valid on SPIFFS). - Returns an empty String if supported, or detail of error(s) if unsupported -*/ -void FSWebServer::checkForUnsupportedPath(String &filename, String &error) -{ - if (!filename.startsWith("/")) - { - error += PSTR(" !! NO_LEADING_SLASH !! "); - } - if (filename.indexOf("//") != -1) - { - error += PSTR(" !! DOUBLE_SLASH !! "); - } - if (filename.endsWith("/")) - { - error += PSTR(" ! TRAILING_SLASH ! "); - } - DebugPrintln(filename); - DebugPrintln(error); -} - -const char *FSWebServer::getContentType(const char *filename) -{ - if (webserver->hasArg("download")) - return PSTR("application/octet-stream"); - else if (strstr(filename, ".htm")) - return PSTR("text/html"); - else if (strstr(filename, ".html")) - return PSTR("text/html"); - else if (strstr(filename, ".css")) - return PSTR("text/css"); - else if (strstr(filename, ".sass")) - return PSTR("text/css"); - else if (strstr(filename, ".js")) - return PSTR("application/javascript"); - else if (strstr(filename, ".png")) - return PSTR("image/png"); - else if (strstr(filename, ".svg")) - return PSTR("image/svg+xml"); - else if (strstr(filename, ".gif")) - return PSTR("image/gif"); - else if (strstr(filename, ".jpg")) - return PSTR("image/jpeg"); - else if (strstr(filename, ".ico")) - return PSTR("image/x-icon"); - else if (strstr(filename, ".xml")) - return PSTR("text/xml"); - else if (strstr(filename, ".pdf")) - return PSTR("application/x-pdf"); - else if (strstr(filename, ".zip")) - return PSTR("application/x-zip"); - else if (strstr(filename, ".gz")) - return PSTR("application/x-gzip"); - return PSTR("text/plain"); -} - -// edit page, in usefull in some situation, but if you need to provide only a web interface, you can disable -#ifdef INCLUDE_EDIT_HTM - -/* - Return the list of files in the directory specified by the "dir" query string parameter. - Also demonstrates the use of chuncked responses. -*/ -void FSWebServer::handleFileList() -{ - if (!webserver->hasArg("dir")) - { - return replyToCLient(BAD_REQUEST, "DIR ARG MISSING"); - } - - String path = webserver->arg("dir"); - DebugPrintln("handleFileList: " + path); - if (path != "/" && !m_filesystem->exists(path)) - { - return replyToCLient(BAD_REQUEST, "BAD PATH"); - } - - File root = m_filesystem->open(path, "r"); - path = String(); - String output; - output.reserve(256); - output = "["; - if (root.isDirectory()) - { - File file = root.openNextFile(); - while (file) - { - String filename = file.name(); - if (filename.lastIndexOf("/") > -1) - { - filename.remove(0, filename.lastIndexOf("/") + 1); - } - if (output != "[") - { - output += ','; - } - output += "{\"type\":\""; - output += (file.isDirectory()) ? "dir" : "file"; - output += "\",\"size\":\""; - output += file.size(); - output += "\",\"name\":\""; - output += filename; - output += "\"}"; - file = root.openNextFile(); - } - } - output += "]"; - webserver->send(200, "text/json", output); -} - -/* - Handle the creation/rename of a new file - Operation | req.responseText - ---------------+-------------------------------------------------------------- - Create file | parent of created file - Create folder | parent of created folder - Rename file | parent of source file - Move file | parent of source file, or remaining ancestor - Rename folder | parent of source folder - Move folder | parent of source folder, or remaining ancestor -*/ -void FSWebServer::handleFileCreate() -{ - String path = webserver->arg("path"); - if (path.isEmpty()) - { - replyToCLient(BAD_REQUEST, PSTR("PATH ARG MISSING")); - return; - } - if (path == "/") - { - replyToCLient(BAD_REQUEST, PSTR("BAD PATH")); - return; - } - - String src = webserver->arg("src"); - if (src.isEmpty()) - { - // No source specified: creation - DebugPrintf_P(PSTR("handleFileCreate: %s\n"), path.c_str()); - if (path.endsWith("/")) - { - // Create a folder - path.remove(path.length() - 1); - if (!m_filesystem->mkdir(path)) - { - replyToCLient(ERROR, PSTR("MKDIR FAILED")); - return; - } - } - else - { - // Create a file - File file = m_filesystem->open(path, "w"); - if (file) - { - file.write(0); - file.close(); - } - else - { - replyToCLient(ERROR, PSTR("CREATE FAILED")); - return; - } - } - replyToCLient(CUSTOM, path.c_str()); - } - else - { - // Source specified: rename - if (src == "/") - { - replyToCLient(BAD_REQUEST, PSTR("BAD SRC")); - return; - } - if (!m_filesystem->exists(src)) - { - replyToCLient(BAD_REQUEST, PSTR("BSRC FILE NOT FOUND")); - return; - } - - DebugPrintf_P(PSTR("handleFileCreate: %s from %s\n"), path.c_str(), src.c_str()); - if (path.endsWith("/")) - { - path.remove(path.length() - 1); - } - if (src.endsWith("/")) - { - src.remove(src.length() - 1); - } - if (!m_filesystem->rename(src, path)) - { - replyToCLient(ERROR, PSTR("RENAME FAILED")); - return; - } - replyOK(); - } -} - -/* - Handle a file deletion request - Operation | req.responseText - ---------------+-------------------------------------------------------------- - Delete file | parent of deleted file, or remaining ancestor - Delete folder | parent of deleted folder, or remaining ancestor -*/ -void FSWebServer::handleFileDelete() -{ - - String path = webserver->arg(0); - if (path.isEmpty() || path == "/") - { - replyToCLient(BAD_REQUEST, PSTR("BAD PATH")); - return; - } - - DebugPrintf_P(PSTR("handleFileDelete: %s\n"), path.c_str()); - if (!m_filesystem->exists(path)) - { - replyToCLient(NOT_FOUND, PSTR(FILE_NOT_FOUND)); - return; - } - // deleteRecursive(path); - File root = m_filesystem->open(path, "r"); - // If it's a plain file, delete it - if (!root.isDirectory()) - { - root.close(); - m_filesystem->remove(path); - replyOK(); - } - else - { - m_filesystem->rmdir(path); - replyOK(); - } -} - -/* - This specific handler returns the edit.htm (or a gzipped version) from the /edit folder. - If the file is not present but the flag INCLUDE_FALLBACK_INDEX_HTM has been set, falls back to the version - embedded in the program code. - Otherwise, fails with a 404 page with debug information -*/ -void FSWebServer::handleGetEdit() -{ -#ifdef INCLUDE_EDIT_HTM - webserver->sendHeader(PSTR("Content-Encoding"), "gzip"); - webserver->send_P(200, "text/html", edit_htm_gz, sizeof(edit_htm_gz)); -#else - replyToCLient(NOT_FOUND, PSTR("FILE_NOT_FOUND")); -#endif -} - -/* - Return the FS type, status and size info -*/ -void FSWebServer::handleStatus() -{ - DebugPrintln(PSTR("handleStatus")); - - size_t totalBytes = 1024; - size_t usedBytes = 0; - -#ifdef ESP8266 - FSInfo fs_info; - m_filesystem->info(fs_info); - totalBytes = fs_info.totalBytes; - usedBytes = fs_info.usedBytes; -#elif defined(ESP32) - totalBytes = LittleFS.totalBytes(); - usedBytes = LittleFS.usedBytes(); -#endif - - String json; - json.reserve(128); - json = "{\"type\":\"Filesystem\", \"isOk\":"; - if (m_fsOK) - { - json += PSTR("\"true\", \"totalBytes\":\""); - json += totalBytes; - json += PSTR("\", \"usedBytes\":\""); - json += usedBytes; - json += "\""; - } - else - json += "\"false\""; - json += PSTR(",\"unsupportedFiles\":\"\"}"); - webserver->send(200, "application/json", json); -} - +#include "esp-fs-webserver.h" + +FSWebServer::FSWebServer(fs::FS &fs, WebServerClass &server) +{ + m_filesystem = &fs; + webserver = &server; + m_basePath[0] = '\0'; +} + +WebServerClass *FSWebServer::getRequest() +{ + return webserver; +} + +void FSWebServer::run() +{ + webserver->handleClient(); + if (m_apmode) + m_dnsServer.processNextRequest(); +} + +void FSWebServer::addHandler(const Uri &uri, HTTPMethod method, WebServerClass::THandlerFunction fn) +{ + webserver->on(uri, method, fn); +} + +void FSWebServer::onNotFound(WebServerClass::THandlerFunction fn) +{ + webserver->onNotFound(fn); +} + +void FSWebServer::addHandler(const Uri &uri, WebServerClass::THandlerFunction handler) +{ + webserver->on(uri, HTTP_ANY, handler); +} + +// List all files saved in the selected filesystem +bool FSWebServer::checkDir(char *dirname, uint8_t levels) +{ + if (dirname[0] != '/') + dirname[0] = '/'; + File root = m_filesystem->open(dirname, "r"); + if (!root) + { + DebugPrintln("- failed to open directory\n"); + return false; + } + if (!root.isDirectory()) + { + DebugPrintln(" - not a directory\n"); + return false; + } + File file = root.openNextFile(); + while (file) + { + if (file.isDirectory()) + { + char dir[16]; + strcpy(dir, "/"); + strcat(dir, file.name()); + DebugPrintf("DIR : %s\n", dir); + checkDir(dir, levels - 1); + } + else + { + DebugPrintf(" FILE: %s\tSIZE: %d\n", file.name(), file.size()); + } + file = root.openNextFile(); + } + return true; +} + +bool FSWebServer::begin(const char *path) +{ + DebugPrintln("\nList the files of webserver: "); + if (path != nullptr) + strcpy(m_basePath, path); + + m_fsOK = checkDir(m_basePath, 2); + +#ifdef INCLUDE_EDIT_HTM + webserver->on("/status", HTTP_GET, std::bind(&FSWebServer::handleStatus, this)); + webserver->on("/list", HTTP_GET, std::bind(&FSWebServer::handleFileList, this)); + webserver->on("/edit", HTTP_GET, std::bind(&FSWebServer::handleGetEdit, this)); + webserver->on("/edit", HTTP_PUT, std::bind(&FSWebServer::handleFileCreate, this)); + webserver->on("/edit", HTTP_DELETE, std::bind(&FSWebServer::handleFileDelete, this)); +#endif + webserver->onNotFound(std::bind(&FSWebServer::handleRequest, this)); + webserver->on("/favicon.ico", HTTP_GET, std::bind(&FSWebServer::replyOK, this)); + webserver->on("/", HTTP_GET, std::bind(&FSWebServer::handleIndex, this)); +#ifdef INCLUDE_SETUP_HTM + webserver->on("/setup", HTTP_GET, std::bind(&FSWebServer::handleSetup, this)); +#endif + webserver->on("/scan", HTTP_GET, std::bind(&FSWebServer::handleScanNetworks, this)); + webserver->on("/connect", HTTP_POST, std::bind(&FSWebServer::doWifiConnection, this)); + webserver->on("/restart", HTTP_GET, std::bind(&FSWebServer::doRestart, this)); + webserver->on("/ipaddress", HTTP_GET, std::bind(&FSWebServer::getIpAddress, this)); + + // Captive Portal redirect + webserver->on("/redirect", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); + // Windows + webserver->on("/connecttest.txt", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); + // Apple + webserver->on("/hotspot-detect.html", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); + // Android + webserver->on("/generate_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); + webserver->on("/gen_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this)); + + // Upload file + // - first callback is called after the request has ended with all parsed arguments + // - second callback handles file upload at that location + webserver->on("/edit", HTTP_POST, std::bind(&FSWebServer::replyOK, this), std::bind(&FSWebServer::handleFileUpload, this)); + + // OTA update via webbrowser + m_httpUpdater.setup(webserver); + + + webserver->enableCORS(true); + + webserver->setContentLength(1024); + webserver->begin(); + + return true; +} + +void FSWebServer::setCaptiveWebage(const char *url) +{ + m_apWebpage = (char *)realloc(m_apWebpage, sizeof(url)); + strcpy(m_apWebpage, url); +} + +IPAddress FSWebServer::setAPmode(const char *ssid, const char *psk) +{ + m_apmode = true; + WiFi.mode(WIFI_AP_STA); + WiFi.persistent(false); + WiFi.softAP(ssid, psk); + /* Setup the DNS server redirecting all the domains to the apIP */ + m_dnsServer.setErrorReplyCode(DNSReplyCode::NoError); + m_dnsServer.start(53, "*", WiFi.softAPIP()); + return WiFi.softAPIP(); +} + +IPAddress FSWebServer::startWiFi(uint32_t timeout, const char *apSSID, const char *apPsw) +{ + IPAddress ip; + m_timeout = timeout; + WiFi.mode(WIFI_STA); + + const char *_ssid; + const char *_pass; + + wifi_config_t conf; + esp_wifi_get_config(WIFI_IF_STA, &conf); + + _ssid = reinterpret_cast(conf.sta.ssid); + _pass = reinterpret_cast(conf.sta.password); + + if (strlen(_ssid) && strlen(_pass)) + { + WiFi.begin(_ssid, _pass); + Serial.print(F("Connecting to ")); + Serial.println(_ssid); + + uint32_t startTime = millis(); + while (WiFi.status() != WL_CONNECTED) + { + delay(300); + Serial.print("."); + if (WiFi.status() == WL_CONNECTED) + { + WiFi.setAutoReconnect(true); + WiFi.persistent(true); + ip = WiFi.localIP(); + return ip; + } + // If no connection after a while go in Access Point mode + if (millis() - startTime > m_timeout) + break; + } + } + + if (apSSID != nullptr && apPsw != nullptr) + setAPmode(apSSID, apPsw); + else + setAPmode("ESP_AP", "123456789"); + + WiFi.begin(); + ip = WiFi.softAPIP(); + Serial.print(F("\nAP mode.\nServer IP address: ")); + Serial.println(ip); + Serial.println(); + return ip; +} + +//////////////////////////////// WiFi ///////////////////////////////////////// + +/** + * Redirect to captive portal if we got a request for another domain. + */ +bool FSWebServer::captivePortal() +{ + IPAddress ip = webserver->client().localIP(); + char serverLoc[sizeof("https:://255.255.255.255/") + sizeof(m_apWebpage) + 1]; + snprintf(serverLoc, sizeof(serverLoc), "http://%d.%d.%d.%d%s", ip[0], ip[1], ip[2], ip[3], m_apWebpage); + + // redirect if hostheader not server ip, prevent redirect loops + if (strcmp(serverLoc, webserver->hostHeader().c_str())) + { + webserver->sendHeader(F("Location"), serverLoc, true); + webserver->send(302, F("text/html"), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + webserver->client().stop(); // Stop is needed because we sent no content length + return true; + } + return false; +} + +void FSWebServer::handleRequest() +{ + if (!m_fsOK) + { + replyToCLient(ERROR, PSTR(FS_INIT_ERROR)); + return; + } +#if defined(ESP32) + String _url = WebServer::urlDecode(webserver->uri()); +#elif defined(ESP8266) + String _url = ESP8266WebServer::urlDecode(webserver->uri()); +#endif + // First try to find and return the requested file from the filesystem, + // and if it fails, return a 404 page with debug information + // Serial.print("urlDecode: "); + // Serial.println(_url); + if (handleFileRead(_url)) + return; + else + replyToCLient(NOT_FOUND, PSTR(FILE_NOT_FOUND)); +} + +void FSWebServer::getIpAddress() +{ + webserver->send(200, "text/json", WiFi.localIP().toString()); +} + +void FSWebServer::doRestart() +{ + Serial.println("RESTART"); + webserver->send(200, "text/json", "Going to restart ESP"); + delay(500); + ESP.restart(); +} + +void FSWebServer::doWifiConnection() +{ + String ssid, pass; + bool persistent = true; + WiFi.mode(WIFI_AP_STA); + + if (webserver->hasArg("ssid")) + { + ssid = webserver->arg("ssid"); + } + + if (webserver->hasArg("password")) + { + pass = webserver->arg("password"); + } + + if (webserver->hasArg("persistent")) + { + String pers = webserver->arg("persistent"); + if (pers.equals("false")) + { + persistent = false; + } + } + + if (WiFi.status() == WL_CONNECTED) + { + + IPAddress ip = WiFi.localIP(); + String resp = "ESP is currently connected to a WiFi network.

" + "Actual connection will be closed and a new attempt will be done with "; + resp += ssid; + resp += " WiFi network."; + webserver->send(200, "text/plain", resp); + + delay(500); + Serial.println("Disconnect from current WiFi network"); + WiFi.disconnect(); + } + + if (ssid.length() && pass.length()) + { + // Try to connect to new ssid + Serial.print("\nConnecting to "); + Serial.println(ssid); + WiFi.begin(ssid.c_str(), pass.c_str()); + + uint32_t beginTime = millis(); + while (WiFi.status() != WL_CONNECTED) + { + delay(300); + Serial.print("*.*"); + if (millis() - beginTime > m_timeout) + break; + } + // reply to client + if (WiFi.status() == WL_CONNECTED) + { + // WiFi.softAPdisconnect(); + IPAddress ip = WiFi.localIP(); + Serial.print("\nConnected to Wifi! IP address: "); + Serial.println(ip); + webserver->send(200, "text/plain", ip.toString()); + m_apmode = false; + delay(500); + ESP.restart(); + // Store current WiFi configuration in flash + if (persistent) + { +#if defined(ESP8266) + struct station_config stationConf; + wifi_station_get_config_default(&stationConf); + // Clear previuos configuration + memset(&stationConf, 0, sizeof(stationConf)); + os_memcpy(&stationConf.ssid, ssid.c_str(), ssid.length()); + os_memcpy(&stationConf.password, pass.c_str(), pass.length()); + wifi_set_opmode(STATION_MODE); + wifi_station_set_config(&stationConf); +#elif defined(ESP32) + wifi_config_t stationConf; + esp_wifi_get_config(WIFI_IF_STA, &stationConf); + // Clear previuos configuration + memset(&stationConf, 0, sizeof(stationConf)); + memcpy(&stationConf.sta.ssid, ssid.c_str(), ssid.length()); + memcpy(&stationConf.sta.password, pass.c_str(), pass.length()); + esp_wifi_set_config(WIFI_IF_STA, &stationConf); +#endif + } + else + { +#if defined(ESP8266) + struct station_config stationConf; + wifi_station_get_config_default(&stationConf); + // Clear previuos configuration + memset(&stationConf, 0, sizeof(stationConf)); + wifi_station_set_config(&stationConf); +#elif defined(ESP32) + wifi_config_t stationConf; + esp_wifi_get_config(WIFI_IF_STA, &stationConf); + // Clear previuos configuration + memset(&stationConf, 0, sizeof(stationConf)); + esp_wifi_set_config(WIFI_IF_STA, &stationConf); +#endif + } + } + else + webserver->send(500, "text/plain", "Connection error, maybe the password is wrong?"); + } + webserver->send(500, "text/plain", "Wrong credentials provided"); +} + +void FSWebServer::setCrossOrigin() +{ + webserver->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + webserver->sendHeader(F("Access-Control-Max-Age"), F("600")); + webserver->sendHeader(F("Access-Control-Allow-Methods"), F("PUT,POST,GET,OPTIONS")); + webserver->sendHeader(F("Access-Control-Allow-Headers"), F("*")); +}; + +void FSWebServer::handleScanNetworks() +{ + String jsonList = "["; + DebugPrint("Scanning WiFi networks..."); + int n = WiFi.scanNetworks(); + DebugPrintln(" complete."); + if (n == 0) + { + DebugPrintln("no networks found"); + webserver->send(200, "text/json", "[]"); + return; + } + else + { + DebugPrint(n); + DebugPrintln(" networks found:"); + + for (int i = 0; i < n; ++i) + { + String ssid = WiFi.SSID(i); + int rssi = WiFi.RSSI(i); +#if defined(ESP8266) + String security = WiFi.encryptionType(i) == AUTH_OPEN ? "none" : "enabled"; +#elif defined(ESP32) + String security = WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "none" : "enabled"; +#endif + jsonList += "{\"ssid\":\""; + jsonList += ssid; + jsonList += "\",\"strength\":\""; + jsonList += rssi; + jsonList += "\",\"security\":"; + jsonList += security == "none" ? "false" : "true"; + jsonList += ssid.equals(WiFi.SSID()) ? ",\"selected\": true" : ""; + jsonList += i < n - 1 ? "}," : "}"; + } + jsonList += "]"; + } + webserver->send(200, "text/json", jsonList); + DebugPrintln(jsonList); +} + +#ifdef INCLUDE_SETUP_HTM + +void FSWebServer::addDropdownList(const char *label, const char **array, size_t size) +{ + File file = m_filesystem->open("/config.json", "r"); + int sz = file.size() * 1.33; + int docSize = max(sz, 2048); + DynamicJsonDocument doc((size_t)docSize); + if (file) + { + // If file is present, load actual configuration + DeserializationError error = deserializeJson(doc, file); + if (error) + { + DebugPrintln(F("Failed to deserialize file, may be corrupted")); + DebugPrintln(error.c_str()); + file.close(); + return; + } + file.close(); + } + else + { + DebugPrintln(F("File not found, will be created new configuration file")); + } + + numOptions++; + + // If key is present in json, we don't need to create it. + if (doc.containsKey(label)) + return; + + JsonObject obj = doc.createNestedObject(label); + obj["selected"] = array[0]; // first element selected as default + JsonArray arr = obj.createNestedArray("values"); + for (int i = 0; i < size; i++) + { + arr.add(array[i]); + } + + file = m_filesystem->open("/config.json", "w"); + if (serializeJsonPretty(doc, file) == 0) + { + DebugPrintln(F("Failed to write to file")); + } + file.close(); +} + +void FSWebServer::removeWhiteSpaces(String &str) +{ + const char noChars[] = {'\n', '\r', '\t'}; + int pos = -1; + // Remove non printable characters + for (int i = 0; i < sizeof(noChars); i++) + { + pos = str.indexOf(noChars[i]); + while (pos > -1) + { + str.replace(String(noChars[i]), ""); + pos = str.indexOf(noChars[i]); + } + } + // Remove doubles spaces + pos = str.indexOf(" "); + while (pos > -1) + { + str.replace(" ", " "); + pos = str.indexOf(" "); + } +} + +void FSWebServer::handleSetup() +{ + webserver->sendHeader(PSTR("Content-Encoding"), "gzip"); + webserver->send_P(200, "text/html", SETUP_HTML, SETUP_HTML_SIZE); +} +#endif + +void FSWebServer::handleIndex() +{ + if (m_filesystem->exists("/index.htm")) + { + handleFileRead("/index.htm"); + } + else if (m_filesystem->exists("/index.html")) + { + handleFileRead("/index.html"); + } +#ifdef INCLUDE_SETUP_HTM + else + { + handleSetup(); + } +#endif +} + +/* + Read the given file from the filesystem and stream it back to the client +*/ +bool FSWebServer::handleFileRead(const String &uri) +{ + String path = m_basePath; + path = uri; + + DebugPrintln("handleFileRead: " + path); + if (path.endsWith("/")) + { + path += "index.htm"; + } + String pathWithGz = path + ".gz"; + + if (m_filesystem->exists(pathWithGz) || m_filesystem->exists(path)) + { + if (m_filesystem->exists(pathWithGz)) + { + path += ".gz"; + } + const char *contentType = getContentType(path.c_str()); + File file = m_filesystem->open(path, "r"); + if (webserver->streamFile(file, contentType) != file.size()) + { + DebugPrintln(PSTR("Sent less data than expected!")); + // webserver->stop(); + } + file.close(); + return true; + } + return false; +} + +/* + Handle a file upload request +*/ +void FSWebServer::handleFileUpload() +{ + if (webserver->uri() != "/edit") + { + return; + } + HTTPUpload &upload = webserver->upload(); + if (upload.status == UPLOAD_FILE_START) + { + String filename = upload.filename; + String result; + // Make sure paths always start with "/" + if (!filename.startsWith("/")) + { + filename = "/" + filename; + } + checkForUnsupportedPath(filename, result); + if (result.length() > 0) + { + replyToCLient(ERROR, PSTR("INVALID FILENAME")); + return; + } + + DebugPrintf_P(PSTR("handleFileUpload Name: %s\n"), filename.c_str()); + m_uploadFile = m_filesystem->open(filename, "w"); + if (!m_uploadFile) + { + replyToCLient(ERROR, PSTR("CREATE FAILED")); + return; + } + DebugPrintf_P(PSTR("Upload: START, filename: %s\n"), filename.c_str()); + } + else if (upload.status == UPLOAD_FILE_WRITE) + { + if (m_uploadFile) + { + size_t bytesWritten = m_uploadFile.write(upload.buf, upload.currentSize); + if (bytesWritten != upload.currentSize) + { + replyToCLient(ERROR, PSTR("WRITE FAILED")); + return; + } + } + DebugPrintf_P(PSTR("Upload: WRITE, Bytes: %d\n"), upload.currentSize); + } + else if (upload.status == UPLOAD_FILE_END) + { + if (m_uploadFile) + { + m_uploadFile.close(); + } + DebugPrintf_P(PSTR("Upload: END, Size: %d\n"), upload.totalSize); + } +} + +void FSWebServer::replyOK() +{ + replyToCLient(OK, ""); +} + +void FSWebServer::replyToCLient(int msg_type = 0, const char *msg = "") +{ + //webserver->sendHeader("Access-Control-Allow-Origin", "*"); + switch (msg_type) + { + case OK: + webserver->send(200, FPSTR(TEXT_PLAIN), ""); + break; + case CUSTOM: + webserver->send(200, FPSTR(TEXT_PLAIN), msg); + break; + case NOT_FOUND: + webserver->send(404, FPSTR(TEXT_PLAIN), msg); + break; + case BAD_REQUEST: + webserver->send(400, FPSTR(TEXT_PLAIN), msg); + break; + case ERROR: + webserver->send(500, FPSTR(TEXT_PLAIN), msg); + break; + } +} + +/* + Checks filename for character combinations that are not supported by FSBrowser (alhtough valid on SPIFFS). + Returns an empty String if supported, or detail of error(s) if unsupported +*/ +void FSWebServer::checkForUnsupportedPath(String &filename, String &error) +{ + if (!filename.startsWith("/")) + { + error += PSTR(" !! NO_LEADING_SLASH !! "); + } + if (filename.indexOf("//") != -1) + { + error += PSTR(" !! DOUBLE_SLASH !! "); + } + if (filename.endsWith("/")) + { + error += PSTR(" ! TRAILING_SLASH ! "); + } + DebugPrintln(filename); + DebugPrintln(error); +} + +const char *FSWebServer::getContentType(const char *filename) +{ + if (webserver->hasArg("download")) + return PSTR("application/octet-stream"); + else if (strstr(filename, ".htm")) + return PSTR("text/html"); + else if (strstr(filename, ".html")) + return PSTR("text/html"); + else if (strstr(filename, ".css")) + return PSTR("text/css"); + else if (strstr(filename, ".sass")) + return PSTR("text/css"); + else if (strstr(filename, ".js")) + return PSTR("application/javascript"); + else if (strstr(filename, ".png")) + return PSTR("image/png"); + else if (strstr(filename, ".svg")) + return PSTR("image/svg+xml"); + else if (strstr(filename, ".gif")) + return PSTR("image/gif"); + else if (strstr(filename, ".jpg")) + return PSTR("image/jpeg"); + else if (strstr(filename, ".ico")) + return PSTR("image/x-icon"); + else if (strstr(filename, ".xml")) + return PSTR("text/xml"); + else if (strstr(filename, ".pdf")) + return PSTR("application/x-pdf"); + else if (strstr(filename, ".zip")) + return PSTR("application/x-zip"); + else if (strstr(filename, ".gz")) + return PSTR("application/x-gzip"); + return PSTR("text/plain"); +} + +// edit page, in usefull in some situation, but if you need to provide only a web interface, you can disable +#ifdef INCLUDE_EDIT_HTM + +/* + Return the list of files in the directory specified by the "dir" query string parameter. + Also demonstrates the use of chuncked responses. +*/ +void FSWebServer::handleFileList() +{ + if (!webserver->hasArg("dir")) + { + return replyToCLient(BAD_REQUEST, "DIR ARG MISSING"); + } + + String path = webserver->arg("dir"); + DebugPrintln("handleFileList: " + path); + if (path != "/" && !m_filesystem->exists(path)) + { + return replyToCLient(BAD_REQUEST, "BAD PATH"); + } + + File root = m_filesystem->open(path, "r"); + path = String(); + String output; + output.reserve(256); + output = "["; + if (root.isDirectory()) + { + File file = root.openNextFile(); + while (file) + { + String filename = file.name(); + if (filename.lastIndexOf("/") > -1) + { + filename.remove(0, filename.lastIndexOf("/") + 1); + } + if (output != "[") + { + output += ','; + } + output += "{\"type\":\""; + output += (file.isDirectory()) ? "dir" : "file"; + output += "\",\"size\":\""; + output += file.size(); + output += "\",\"name\":\""; + output += filename; + output += "\"}"; + file = root.openNextFile(); + } + } + output += "]"; + webserver->send(200, "text/json", output); +} + +/* + Handle the creation/rename of a new file + Operation | req.responseText + ---------------+-------------------------------------------------------------- + Create file | parent of created file + Create folder | parent of created folder + Rename file | parent of source file + Move file | parent of source file, or remaining ancestor + Rename folder | parent of source folder + Move folder | parent of source folder, or remaining ancestor +*/ +void FSWebServer::handleFileCreate() +{ + String path = webserver->arg("path"); + if (path.isEmpty()) + { + replyToCLient(BAD_REQUEST, PSTR("PATH ARG MISSING")); + return; + } + if (path == "/") + { + replyToCLient(BAD_REQUEST, PSTR("BAD PATH")); + return; + } + + String src = webserver->arg("src"); + if (src.isEmpty()) + { + // No source specified: creation + DebugPrintf_P(PSTR("handleFileCreate: %s\n"), path.c_str()); + if (path.endsWith("/")) + { + // Create a folder + path.remove(path.length() - 1); + if (!m_filesystem->mkdir(path)) + { + replyToCLient(ERROR, PSTR("MKDIR FAILED")); + return; + } + } + else + { + // Create a file + File file = m_filesystem->open(path, "w"); + if (file) + { + file.write(0); + file.close(); + } + else + { + replyToCLient(ERROR, PSTR("CREATE FAILED")); + return; + } + } + replyToCLient(CUSTOM, path.c_str()); + } + else + { + // Source specified: rename + if (src == "/") + { + replyToCLient(BAD_REQUEST, PSTR("BAD SRC")); + return; + } + if (!m_filesystem->exists(src)) + { + replyToCLient(BAD_REQUEST, PSTR("BSRC FILE NOT FOUND")); + return; + } + + DebugPrintf_P(PSTR("handleFileCreate: %s from %s\n"), path.c_str(), src.c_str()); + if (path.endsWith("/")) + { + path.remove(path.length() - 1); + } + if (src.endsWith("/")) + { + src.remove(src.length() - 1); + } + if (!m_filesystem->rename(src, path)) + { + replyToCLient(ERROR, PSTR("RENAME FAILED")); + return; + } + replyOK(); + } +} + +/* + Handle a file deletion request + Operation | req.responseText + ---------------+-------------------------------------------------------------- + Delete file | parent of deleted file, or remaining ancestor + Delete folder | parent of deleted folder, or remaining ancestor +*/ +void FSWebServer::handleFileDelete() +{ + + String path = webserver->arg(0); + if (path.isEmpty() || path == "/") + { + replyToCLient(BAD_REQUEST, PSTR("BAD PATH")); + return; + } + + DebugPrintf_P(PSTR("handleFileDelete: %s\n"), path.c_str()); + if (!m_filesystem->exists(path)) + { + replyToCLient(NOT_FOUND, PSTR(FILE_NOT_FOUND)); + return; + } + // deleteRecursive(path); + File root = m_filesystem->open(path, "r"); + // If it's a plain file, delete it + if (!root.isDirectory()) + { + root.close(); + m_filesystem->remove(path); + replyOK(); + } + else + { + m_filesystem->rmdir(path); + replyOK(); + } +} + +/* + This specific handler returns the edit.htm (or a gzipped version) from the /edit folder. + If the file is not present but the flag INCLUDE_FALLBACK_INDEX_HTM has been set, falls back to the version + embedded in the program code. + Otherwise, fails with a 404 page with debug information +*/ +void FSWebServer::handleGetEdit() +{ +#ifdef INCLUDE_EDIT_HTM + webserver->sendHeader(PSTR("Content-Encoding"), "gzip"); + webserver->send_P(200, "text/html", edit_htm_gz, sizeof(edit_htm_gz)); +#else + replyToCLient(NOT_FOUND, PSTR("FILE_NOT_FOUND")); +#endif +} + +/* + Return the FS type, status and size info +*/ +void FSWebServer::handleStatus() +{ + DebugPrintln(PSTR("handleStatus")); + + size_t totalBytes = 1024; + size_t usedBytes = 0; + +#ifdef ESP8266 + FSInfo fs_info; + m_filesystem->info(fs_info); + totalBytes = fs_info.totalBytes; + usedBytes = fs_info.usedBytes; +#elif defined(ESP32) + totalBytes = LittleFS.totalBytes(); + usedBytes = LittleFS.usedBytes(); +#endif + + String json; + json.reserve(128); + json = "{\"type\":\"Filesystem\", \"isOk\":"; + if (m_fsOK) + { + json += PSTR("\"true\", \"totalBytes\":\""); + json += totalBytes; + json += PSTR("\", \"usedBytes\":\""); + json += usedBytes; + json += "\""; + } + else + json += "\"false\""; + json += PSTR(",\"unsupportedFiles\":\"\"}"); + webserver->send(200, "application/json", json); +} + #endif // INCLUDE_EDIT_HTM \ No newline at end of file diff --git a/lib/webserver/src/esp-fs-webserver.h b/lib/webserver/esp-fs-webserver.h similarity index 96% rename from lib/webserver/src/esp-fs-webserver.h rename to lib/webserver/esp-fs-webserver.h index 9701dbe4..ee35fc10 100644 --- a/lib/webserver/src/esp-fs-webserver.h +++ b/lib/webserver/esp-fs-webserver.h @@ -1,347 +1,347 @@ -#ifndef esp_fs_webserver_H -#define esp_fs_webserver_H - -#include -#include -#include -#include -// #include -#include - -#define INCLUDE_EDIT_HTM -#ifdef INCLUDE_EDIT_HTM -#include "edit_htm.h" -#endif - -#define INCLUDE_SETUP_HTM -#ifdef INCLUDE_SETUP_HTM -#define ARDUINOJSON_USE_LONG_LONG 1 -#include -#include "setup_htm.h" -#endif - -#if defined(ESP8266) -#include -#include -#include -#include // from Arduino core, OTA update via webbrowser -using WebServerClass = ESP8266WebServer; -using UpdateServerClass = ESP8266HTTPUpdateServer; -#elif defined(ESP32) -#include -#include -#include -#include -#include // from Arduino core, OTA update via webbrowser -using WebServerClass = WebServer; -using UpdateServerClass = HTTPUpdateServer; -#endif -#include - -#ifndef DEBUG_ESP_PORT -#define DBG_OUTPUT_PORT Serial -#define DEBUG_MODE_WS false -#else -#define DBG_OUTPUT_PORT DEBUG_ESP_PORT -#endif - -#if DEBUG_MODE_WS -#define DebugPrint(x) DBG_OUTPUT_PORT.print(x) -#define DebugPrintln(x) DBG_OUTPUT_PORT.println(x) -#define DebugPrintf(fmt, ...) DBG_OUTPUT_PORT.printf(fmt, ##__VA_ARGS__) -#define DebugPrintf_P(fmt, ...) DBG_OUTPUT_PORT.printf_P(fmt, ##__VA_ARGS__) -#else -#define DebugPrint(x) -#define DebugPrintln(x) -#define DebugPrintf(x, ...) -#define DebugPrintf_P(x, ...) -#endif - -enum -{ - MSG_OK, - CUSTOM, - NOT_FOUND, - BAD_REQUEST, - ERROR -}; -#define TEXT_PLAIN "text/plain" -#define FS_INIT_ERROR "FS INIT ERROR" -#define FILE_NOT_FOUND "FileNotFound" - -class FSWebServer -{ - - // using CallbackF = std::function; - -public: - WebServerClass *webserver; - - FSWebServer(fs::FS &fs, WebServerClass &server); - - bool begin(const char *path = nullptr); - - void run(); - void onNotFound(WebServerClass::THandlerFunction fn); - - void addHandler(const Uri &uri, HTTPMethod method, WebServerClass::THandlerFunction fn); - - void addHandler(const Uri &uri, WebServerClass::THandlerFunction handler); - - void setCaptiveWebage(const char *url); - - IPAddress setAPmode(const char *ssid, const char *psk); - - IPAddress startWiFi(uint32_t timeout, const char *apSSID, const char *apPsw); - - WebServerClass *getRequest(); - -#ifdef INCLUDE_SETUP_HTM - -#define MIN_F -3.4028235E+38 -#define MAX_F 3.4028235E+38 - - inline bool clearOptions() - { - File file = m_filesystem->open("/config.json", "r"); - if (file) - { - file.close(); - m_filesystem->remove("/config.json"); - return true; - } - return false; - } - - inline void addOptionBox(const char *boxTitle) - { - addOption("param-box", boxTitle, false); - } - - inline void addHTML(const char *html, const char *id) - { - String elementId = "raw-html-"; - elementId += id; - String trimmed = html; - removeWhiteSpaces(trimmed); - addOption(elementId.c_str(), trimmed.c_str(), false); - } - - inline void addCSS(const char *css) - { - String trimmed = css; - removeWhiteSpaces(trimmed); - addOption("raw-css", trimmed.c_str(), false); - } - - inline void addJavascript(const char *script) - { - // String trimmed = script; - // removeWhiteSpaces(trimmed); - addOption("raw-javascript", script, true); - } - - void addDropdownList(const char *label, const char **array, size_t size); - - // Only for backward-compatibility - template - inline void addOption(fs::FS &fs, const char *label, T val, bool hidden = false) - { - addOption(label, val, hidden); - } - - // Add custom option to config webpage (float values) - template - inline void addOption(const char *label, T val, double d_min, double d_max, double step) - { - addOption(label, val, false, d_min, d_max, step); - } - - // Add custom option to config webpage (type of parameter will be deduced from variable itself) - template - inline void addOption(const char *label, T val, bool hidden = false, - double d_min = MIN_F, double d_max = MAX_F, double step = 1.0) - { - File file = m_filesystem->open("/config.json", "r"); - int sz = file.size() * 1.33; - int docSize = max(sz, 2048); - DynamicJsonDocument doc((size_t)docSize); - if (file) - { - // If file is present, load actual configuration - DeserializationError error = deserializeJson(doc, file); - if (error) - { - DebugPrintln(F("Failed to deserialize file, may be corrupted")); - DebugPrintln(error.c_str()); - file.close(); - return; - } - file.close(); - } - else - { - DebugPrintln(F("File not found, will be created new configuration file")); - } - - numOptions++; - - String key = label; - if (hidden) - key += "-hidden"; - - // Univoque key name - if (key.equals("param-box")) - { - key += numOptions; - } - if (key.equals("raw-javascript")) - { - key += numOptions; - } - - // If key is present in json, we don't need to create it. - if (doc.containsKey(key.c_str())) - return; - - // if min, max, step != from default, treat this as object in order to set other properties - if (d_min != MIN_F || d_max != MAX_F || step != 1.0) - { - JsonObject obj = doc.createNestedObject(key); - obj["value"] = static_cast(val); - obj["min"] = d_min; - obj["max"] = d_max; - obj["step"] = step; - } - else - { - doc[key] = static_cast(val); - } - - file = m_filesystem->open("/config.json", "w"); - if (serializeJsonPretty(doc, file) == 0) - { - DebugPrintln(F("Failed to write to file")); - } - file.close(); - } - - // Get current value for a specific custom option (true on success) - template - bool getOptionValue(const char *label, T &var) - { - File file = m_filesystem->open("/config.json", "r"); - DynamicJsonDocument doc(file.size() * 1.33); - if (file) - { - DeserializationError error = deserializeJson(doc, file); - if (error) - { - DebugPrintln(F("Failed to deserialize file, may be corrupted")); - DebugPrintln(error.c_str()); - file.close(); - return false; - } - file.close(); - } - else - return false; - - if (doc[label]["value"]) - var = doc[label]["value"].as(); - else if (doc[label]["selected"]) - var = doc[label]["selected"].as(); - else - var = doc[label].as(); - return true; - } - - template - bool saveOptionValue(const char *label, T val) - { - // Öffne die Datei im Lesemodus, um den Inhalt des Dokuments beizubehalten - File file = m_filesystem->open("/config.json", "r"); - DynamicJsonDocument doc(file.size() * 1.33); - - if (file) - { - // Deserialisiere das JSON-Dokument aus der Datei - DeserializationError error = deserializeJson(doc, file); - if (error) - { - DebugPrintln(F("Failed to deserialize file, may be corrupted")); - DebugPrintln(error.c_str()); - file.close(); - return false; - } - file.close(); - } - - // Füge den Schlüssel mit dem neuen Wert hinzu, falls er nicht vorhanden ist - if (!doc.containsKey(label)) - { - doc[label] = val; - } - else - { - // Ändere den Wert mit dem Schlüssel "label" - JsonVariant option = doc[label]; - option.set(val); - } - - // Öffne die Datei im Schreibmodus und speichere das geänderte Dokument - file = m_filesystem->open("/config.json", "w"); - if (!file) - return false; - serializeJsonPretty(doc, file); - file.close(); - - return true; - } - -#endif - -private: - char m_basePath[16]; - UpdateServerClass m_httpUpdater; - DNSServer m_dnsServer; - fs::FS *m_filesystem; - File m_uploadFile; - bool m_fsOK = false; - bool m_apmode = false; - char *m_apWebpage = (char *)"/setup"; - uint32_t m_timeout = 10000; - - // Default handler for all URIs not defined above, use it to read files from filesystem - bool checkDir(char *dirname, uint8_t levels); - void doWifiConnection(); - void doRestart(); - void replyOK(); - void getIpAddress(); - void handleRequest(); -#ifdef INCLUDE_SETUP_HTM - void removeWhiteSpaces(String &str); - void handleSetup(); - uint8_t numOptions = 0; -#endif - void handleIndex(); - bool handleFileRead(const String &path); - void handleFileUpload(); - void replyToCLient(int msg_type, const char *msg); - void checkForUnsupportedPath(String &filename, String &error); - void setCrossOrigin(); - void handleScanNetworks(); - const char *getContentType(const char *filename); - bool captivePortal(); - - // edit page, in usefull in some situation, but if you need to provide only a web interface, you can disable -#ifdef INCLUDE_EDIT_HTM - void handleGetEdit(); - void handleFileCreate(); - void handleFileDelete(); - void handleStatus(); - void handleFileList(); -#endif -}; - -#endif +#ifndef esp_fs_webserver_H +#define esp_fs_webserver_H + +#include +#include +#include +#include +// #include +#include + +#define INCLUDE_EDIT_HTM +#ifdef INCLUDE_EDIT_HTM +#include "edit_htm.h" +#endif + +#define INCLUDE_SETUP_HTM +#ifdef INCLUDE_SETUP_HTM +#define ARDUINOJSON_USE_LONG_LONG 1 +#include +#include "setup_htm.h" +#endif + +#if defined(ESP8266) +#include +#include +#include +#include // from Arduino core, OTA update via webbrowser +using WebServerClass = ESP8266WebServer; +using UpdateServerClass = ESP8266HTTPUpdateServer; +#elif defined(ESP32) +#include +#include +#include +#include +#include // from Arduino core, OTA update via webbrowser +using WebServerClass = WebServer; +using UpdateServerClass = HTTPUpdateServer; +#endif +#include + +#ifndef DEBUG_ESP_PORT +#define DBG_OUTPUT_PORT Serial +#define DEBUG_MODE_WS false +#else +#define DBG_OUTPUT_PORT DEBUG_ESP_PORT +#endif + +#if DEBUG_MODE_WS +#define DebugPrint(x) DBG_OUTPUT_PORT.print(x) +#define DebugPrintln(x) DBG_OUTPUT_PORT.println(x) +#define DebugPrintf(fmt, ...) DBG_OUTPUT_PORT.printf(fmt, ##__VA_ARGS__) +#define DebugPrintf_P(fmt, ...) DBG_OUTPUT_PORT.printf_P(fmt, ##__VA_ARGS__) +#else +#define DebugPrint(x) +#define DebugPrintln(x) +#define DebugPrintf(x, ...) +#define DebugPrintf_P(x, ...) +#endif + +enum +{ + MSG_OK, + CUSTOM, + NOT_FOUND, + BAD_REQUEST, + ERROR +}; +#define TEXT_PLAIN "text/plain" +#define FS_INIT_ERROR "FS INIT ERROR" +#define FILE_NOT_FOUND "FileNotFound" + +class FSWebServer +{ + + // using CallbackF = std::function; + +public: + WebServerClass *webserver; + + FSWebServer(fs::FS &fs, WebServerClass &server); + + bool begin(const char *path = nullptr); + + void run(); + void onNotFound(WebServerClass::THandlerFunction fn); + + void addHandler(const Uri &uri, HTTPMethod method, WebServerClass::THandlerFunction fn); + + void addHandler(const Uri &uri, WebServerClass::THandlerFunction handler); + + void setCaptiveWebage(const char *url); + + IPAddress setAPmode(const char *ssid, const char *psk); + + IPAddress startWiFi(uint32_t timeout, const char *apSSID, const char *apPsw); + + WebServerClass *getRequest(); + +#ifdef INCLUDE_SETUP_HTM + +#define MIN_F -3.4028235E+38 +#define MAX_F 3.4028235E+38 + + inline bool clearOptions() + { + File file = m_filesystem->open("/config.json", "r"); + if (file) + { + file.close(); + m_filesystem->remove("/config.json"); + return true; + } + return false; + } + + inline void addOptionBox(const char *boxTitle) + { + addOption("param-box", boxTitle, false); + } + + inline void addHTML(const char *html, const char *id) + { + String elementId = "raw-html-"; + elementId += id; + String trimmed = html; + removeWhiteSpaces(trimmed); + addOption(elementId.c_str(), trimmed.c_str(), false); + } + + inline void addCSS(const char *css) + { + String trimmed = css; + removeWhiteSpaces(trimmed); + addOption("raw-css", trimmed.c_str(), false); + } + + inline void addJavascript(const char *script) + { + // String trimmed = script; + // removeWhiteSpaces(trimmed); + addOption("raw-javascript", script, true); + } + + void addDropdownList(const char *label, const char **array, size_t size); + + // Only for backward-compatibility + template + inline void addOption(fs::FS &fs, const char *label, T val, bool hidden = false) + { + addOption(label, val, hidden); + } + + // Add custom option to config webpage (float values) + template + inline void addOption(const char *label, T val, double d_min, double d_max, double step) + { + addOption(label, val, false, d_min, d_max, step); + } + + // Add custom option to config webpage (type of parameter will be deduced from variable itself) + template + inline void addOption(const char *label, T val, bool hidden = false, + double d_min = MIN_F, double d_max = MAX_F, double step = 1.0) + { + File file = m_filesystem->open("/config.json", "r"); + int sz = file.size() * 1.33; + int docSize = max(sz, 2048); + DynamicJsonDocument doc((size_t)docSize); + if (file) + { + // If file is present, load actual configuration + DeserializationError error = deserializeJson(doc, file); + if (error) + { + DebugPrintln(F("Failed to deserialize file, may be corrupted")); + DebugPrintln(error.c_str()); + file.close(); + return; + } + file.close(); + } + else + { + DebugPrintln(F("File not found, will be created new configuration file")); + } + + numOptions++; + + String key = label; + if (hidden) + key += "-hidden"; + + // Univoque key name + if (key.equals("param-box")) + { + key += numOptions; + } + if (key.equals("raw-javascript")) + { + key += numOptions; + } + + // If key is present in json, we don't need to create it. + if (doc.containsKey(key.c_str())) + return; + + // if min, max, step != from default, treat this as object in order to set other properties + if (d_min != MIN_F || d_max != MAX_F || step != 1.0) + { + JsonObject obj = doc.createNestedObject(key); + obj["value"] = static_cast(val); + obj["min"] = d_min; + obj["max"] = d_max; + obj["step"] = step; + } + else + { + doc[key] = static_cast(val); + } + + file = m_filesystem->open("/config.json", "w"); + if (serializeJsonPretty(doc, file) == 0) + { + DebugPrintln(F("Failed to write to file")); + } + file.close(); + } + + // Get current value for a specific custom option (true on success) + template + bool getOptionValue(const char *label, T &var) + { + File file = m_filesystem->open("/config.json", "r"); + DynamicJsonDocument doc(file.size() * 1.33); + if (file) + { + DeserializationError error = deserializeJson(doc, file); + if (error) + { + DebugPrintln(F("Failed to deserialize file, may be corrupted")); + DebugPrintln(error.c_str()); + file.close(); + return false; + } + file.close(); + } + else + return false; + + if (doc[label]["value"]) + var = doc[label]["value"].as(); + else if (doc[label]["selected"]) + var = doc[label]["selected"].as(); + else + var = doc[label].as(); + return true; + } + + template + bool saveOptionValue(const char *label, T val) + { + // Öffne die Datei im Lesemodus, um den Inhalt des Dokuments beizubehalten + File file = m_filesystem->open("/config.json", "r"); + DynamicJsonDocument doc(file.size() * 1.33); + + if (file) + { + // Deserialisiere das JSON-Dokument aus der Datei + DeserializationError error = deserializeJson(doc, file); + if (error) + { + DebugPrintln(F("Failed to deserialize file, may be corrupted")); + DebugPrintln(error.c_str()); + file.close(); + return false; + } + file.close(); + } + + // Füge den Schlüssel mit dem neuen Wert hinzu, falls er nicht vorhanden ist + if (!doc.containsKey(label)) + { + doc[label] = val; + } + else + { + // Ändere den Wert mit dem Schlüssel "label" + JsonVariant option = doc[label]; + option.set(val); + } + + // Öffne die Datei im Schreibmodus und speichere das geänderte Dokument + file = m_filesystem->open("/config.json", "w"); + if (!file) + return false; + serializeJsonPretty(doc, file); + file.close(); + + return true; + } + +#endif + +private: + char m_basePath[16]; + UpdateServerClass m_httpUpdater; + DNSServer m_dnsServer; + fs::FS *m_filesystem; + File m_uploadFile; + bool m_fsOK = false; + bool m_apmode = false; + char *m_apWebpage = (char *)"/setup"; + uint32_t m_timeout = 10000; + + // Default handler for all URIs not defined above, use it to read files from filesystem + bool checkDir(char *dirname, uint8_t levels); + void doWifiConnection(); + void doRestart(); + void replyOK(); + void getIpAddress(); + void handleRequest(); +#ifdef INCLUDE_SETUP_HTM + void removeWhiteSpaces(String &str); + void handleSetup(); + uint8_t numOptions = 0; +#endif + void handleIndex(); + bool handleFileRead(const String &path); + void handleFileUpload(); + void replyToCLient(int msg_type, const char *msg); + void checkForUnsupportedPath(String &filename, String &error); + void setCrossOrigin(); + void handleScanNetworks(); + const char *getContentType(const char *filename); + bool captivePortal(); + + // edit page, in usefull in some situation, but if you need to provide only a web interface, you can disable +#ifdef INCLUDE_EDIT_HTM + void handleGetEdit(); + void handleFileCreate(); + void handleFileDelete(); + void handleStatus(); + void handleFileList(); +#endif +}; + +#endif diff --git a/lib/webserver/src/linked_list.h b/lib/webserver/linked_list.h similarity index 97% rename from lib/webserver/src/linked_list.h rename to lib/webserver/linked_list.h index 8de2ca46..6a876edb 100644 --- a/lib/webserver/src/linked_list.h +++ b/lib/webserver/linked_list.h @@ -1,163 +1,163 @@ -#define VAR_NAME(name) #name - -#include -#include - -#ifndef linked_list_H -#define linked_list_H - - -#if DEBUG_MODE -#define DebugPrint(x) DBG_OUTPUT_PORT.print(x) -#define DebugPrintln(x) DBG_OUTPUT_PORT.println(x) -#define DebugPrintf(fmt, ...) DBG_OUTPUT_PORT.printf(fmt, ##__VA_ARGS__) -#define DebugPrintf_P(fmt, ...) DBG_OUTPUT_PORT.printf_P(fmt, ##__VA_ARGS__) -#else -#define DebugPrint(x) -#define DebugPrintln(x) -#define DebugPrintf(x, ...) -#define DebugPrintf_P(x, ...) -#endif - - -enum { CHAR, UCHAR, CHAR_PT, BOOL, INT, LONG, UINT, ULONG, FLOAT, DOUBLE, STRING}; - -//////////////////////////////////////////////////////////////// -struct VarNode -{ - uint8_t type; - void* var; - const char* key; - VarNode* next = nullptr; -}; -//////////////////////////////////////////////////////////////// -class VariableList -{ - private: - VarNode* first = nullptr; - VarNode* last = nullptr; - - public: - VariableList(){;} - - template - void addItem(T& var, const char* key) - { - VarNode* node = new VarNode(); - node->var = &var; - // node->key = VAR_NAME(var); - node->key = key; - node->type = TypeOf(var); - - if (first == nullptr) { - first = node; - last = node; - return; - } - last->next = node; - last = node; - } - - VarNode* getNode(const char* key) - { - VarNode* current = first; - while ( current != nullptr ) - { - if (strcmp(current->key, key) == 0) { - return current; - } - current = current->next; - } - return nullptr; - } - - - bool saveValues(fs::FS *fs, const char* filename) { - File file = fs->open("/config.json", "w"); - int sz = file.size() * 1.33; - int docSize = max(sz, 2048); - DynamicJsonDocument root((size_t)docSize); - if (!file) - { - DebugPrintln(F("File not found, will be created new configuration file")); - return false; - } - - VarNode* current = first; - while ( current != nullptr ) - { - switch (current->type) { - case BOOL: root[current->key] = *(bool*)current->var; break; - case CHAR: root[current->key] = *(signed char*)current->var; break; - case INT: root[current->key] = *(int*)current->var; break; - case LONG: root[current->key] = *(long*)current->var; break; - case UCHAR: root[current->key] = *(unsigned char*)current->var; break; - case UINT: root[current->key] = *(unsigned int*)current->var; break; - case ULONG: root[current->key] = *(unsigned long*)current->var; break; - case CHAR_PT: root[current->key] = (unsigned char*)current->var; break; - case FLOAT: root[current->key] = *(float*)current->var; break; - case DOUBLE: root[current->key] = *(double*)current->var; break; - case STRING: root[current->key] = *(String*)current->var; break; - } - current = current->next; - } - - serializeJson(root, file); - file.close(); - return true; - } - - bool loadValues(fs::FS *fs, const char* filename) { - File file = fs->open("/config.json", "r"); - DynamicJsonDocument doc(file.size() * 1.33); - if (file) - { - DeserializationError error = deserializeJson(doc, file); - if (error) - { - DebugPrintln(F("Failed to deserialize file, may be corrupted")); - DebugPrintln(error.c_str()); - file.close(); - return false; - } - file.close(); - } - else - return false; - - VarNode* current = first; - while ( current != nullptr ) - { - switch (current->type) { - case BOOL: *(bool*)current->var = doc[current->key]; break; - case CHAR: *(signed char*)current->var = doc[current->key]; break; - case INT: *(int*)current->var = doc[current->key]; break; - case LONG: *(long*)current->var = doc[current->key]; break; - case UCHAR: *(unsigned char*)current->var = doc[current->key]; break; - case UINT: *(unsigned int*)current->var = doc[current->key]; break; - case ULONG: *(unsigned long*)current->var = doc[current->key]; break; - case CHAR_PT: strcpy((char*)current->var, doc[current->key]); break; - case FLOAT: *(float*)current->var = doc[current->key]; break; - case DOUBLE: *(double*)current->var = doc[current->key]; break; - case STRING: *(String*)current->var = doc[current->key].as(); break; - } - current = current->next; - } - - return true; - } - - - virtual inline uint8_t TypeOf(const bool&) { return BOOL; } - virtual inline uint8_t TypeOf(const char&) { return CHAR; } - virtual inline uint8_t TypeOf(const char*) { return CHAR_PT; } - virtual inline uint8_t TypeOf(const double&) { return DOUBLE; } - virtual inline uint8_t TypeOf(const float&) { return FLOAT; } - virtual inline uint8_t TypeOf(const int&) { return INT; } - virtual inline uint8_t TypeOf(const unsigned int&) { return UINT; } - virtual inline uint8_t TypeOf(const unsigned long&) { return ULONG; } - virtual inline uint8_t TypeOf(const unsigned char&) { return UCHAR; } - virtual inline uint8_t TypeOf(const String&) { return STRING; } -}; - +#define VAR_NAME(name) #name + +#include +#include + +#ifndef linked_list_H +#define linked_list_H + + +#if DEBUG_MODE +#define DebugPrint(x) DBG_OUTPUT_PORT.print(x) +#define DebugPrintln(x) DBG_OUTPUT_PORT.println(x) +#define DebugPrintf(fmt, ...) DBG_OUTPUT_PORT.printf(fmt, ##__VA_ARGS__) +#define DebugPrintf_P(fmt, ...) DBG_OUTPUT_PORT.printf_P(fmt, ##__VA_ARGS__) +#else +#define DebugPrint(x) +#define DebugPrintln(x) +#define DebugPrintf(x, ...) +#define DebugPrintf_P(x, ...) +#endif + + +enum { CHAR, UCHAR, CHAR_PT, BOOL, INT, LONG, UINT, ULONG, FLOAT, DOUBLE, STRING}; + +//////////////////////////////////////////////////////////////// +struct VarNode +{ + uint8_t type; + void* var; + const char* key; + VarNode* next = nullptr; +}; +//////////////////////////////////////////////////////////////// +class VariableList +{ + private: + VarNode* first = nullptr; + VarNode* last = nullptr; + + public: + VariableList(){;} + + template + void addItem(T& var, const char* key) + { + VarNode* node = new VarNode(); + node->var = &var; + // node->key = VAR_NAME(var); + node->key = key; + node->type = TypeOf(var); + + if (first == nullptr) { + first = node; + last = node; + return; + } + last->next = node; + last = node; + } + + VarNode* getNode(const char* key) + { + VarNode* current = first; + while ( current != nullptr ) + { + if (strcmp(current->key, key) == 0) { + return current; + } + current = current->next; + } + return nullptr; + } + + + bool saveValues(fs::FS *fs, const char* filename) { + File file = fs->open("/config.json", "w"); + int sz = file.size() * 1.33; + int docSize = max(sz, 2048); + DynamicJsonDocument root((size_t)docSize); + if (!file) + { + DebugPrintln(F("File not found, will be created new configuration file")); + return false; + } + + VarNode* current = first; + while ( current != nullptr ) + { + switch (current->type) { + case BOOL: root[current->key] = *(bool*)current->var; break; + case CHAR: root[current->key] = *(signed char*)current->var; break; + case INT: root[current->key] = *(int*)current->var; break; + case LONG: root[current->key] = *(long*)current->var; break; + case UCHAR: root[current->key] = *(unsigned char*)current->var; break; + case UINT: root[current->key] = *(unsigned int*)current->var; break; + case ULONG: root[current->key] = *(unsigned long*)current->var; break; + case CHAR_PT: root[current->key] = (unsigned char*)current->var; break; + case FLOAT: root[current->key] = *(float*)current->var; break; + case DOUBLE: root[current->key] = *(double*)current->var; break; + case STRING: root[current->key] = *(String*)current->var; break; + } + current = current->next; + } + + serializeJson(root, file); + file.close(); + return true; + } + + bool loadValues(fs::FS *fs, const char* filename) { + File file = fs->open("/config.json", "r"); + DynamicJsonDocument doc(file.size() * 1.33); + if (file) + { + DeserializationError error = deserializeJson(doc, file); + if (error) + { + DebugPrintln(F("Failed to deserialize file, may be corrupted")); + DebugPrintln(error.c_str()); + file.close(); + return false; + } + file.close(); + } + else + return false; + + VarNode* current = first; + while ( current != nullptr ) + { + switch (current->type) { + case BOOL: *(bool*)current->var = doc[current->key]; break; + case CHAR: *(signed char*)current->var = doc[current->key]; break; + case INT: *(int*)current->var = doc[current->key]; break; + case LONG: *(long*)current->var = doc[current->key]; break; + case UCHAR: *(unsigned char*)current->var = doc[current->key]; break; + case UINT: *(unsigned int*)current->var = doc[current->key]; break; + case ULONG: *(unsigned long*)current->var = doc[current->key]; break; + case CHAR_PT: strcpy((char*)current->var, doc[current->key]); break; + case FLOAT: *(float*)current->var = doc[current->key]; break; + case DOUBLE: *(double*)current->var = doc[current->key]; break; + case STRING: *(String*)current->var = doc[current->key].as(); break; + } + current = current->next; + } + + return true; + } + + + virtual inline uint8_t TypeOf(const bool&) { return BOOL; } + virtual inline uint8_t TypeOf(const char&) { return CHAR; } + virtual inline uint8_t TypeOf(const char*) { return CHAR_PT; } + virtual inline uint8_t TypeOf(const double&) { return DOUBLE; } + virtual inline uint8_t TypeOf(const float&) { return FLOAT; } + virtual inline uint8_t TypeOf(const int&) { return INT; } + virtual inline uint8_t TypeOf(const unsigned int&) { return UINT; } + virtual inline uint8_t TypeOf(const unsigned long&) { return ULONG; } + virtual inline uint8_t TypeOf(const unsigned char&) { return UCHAR; } + virtual inline uint8_t TypeOf(const String&) { return STRING; } +}; + #endif \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/app.js b/lib/webserver/setup-ui/data/app.js deleted file mode 100644 index 42498c3c..00000000 --- a/lib/webserver/setup-ui/data/app.js +++ /dev/null @@ -1,484 +0,0 @@ -svgLogo = ''; -const svgMenu = ''; -const svgLock = ''; -const svgUnlock = ''; -const svgScan = ''; -const svgConnect = ''; -const svgSave = ''; -const svgRestart = ''; -const svgEye = ''; -const svgNoEye = ''; -const svgCloseModal = ''; - -var options = {}; - -// Simple JQuery-like selector -var $ = function (el) { - return document.getElementById(el); -}; - - -function showHidePassword() { - var inp = $("password"); - openModalMessage('Restart!', '
ESP restarted. Please wait a little and then reload this page.
'); - if (inp.type === "password") { - inp.type = "text"; - $('show-pass').classList.remove("w--current"); - $('hide-pass').classList.add("w--current"); - } - else { - inp.type = "password"; - $('show-pass').classList.add("w--current"); - $('hide-pass').classList.remove("w--current"); - } -} - -/** -* Read some data from database -*/ -function getWiFiList() { - $('loader').classList.remove('hide'); - var url = new URL("http://" + `${window.location.hostname}` + "/scan"); - fetch(url) - .then(response => response.json()) - .then(data => { - listWifiNetworks(data); - $('loader').classList.add('hide'); - }); -} - - -function selectWifi(row) { - try { - $('select-' + row.target.parentNode.id).checked = true; - } - catch (err) { - $(row.target.id).checked = true; - } - $('ssid').value = this.cells[1].innerHTML; - $('ssid-name').innerHTML = this.cells[1].innerHTML; - $('password').focus(); -} - - -function listWifiNetworks(elems) { - const list = document.querySelector('#wifi-list'); - list.innerHTML = ""; - elems.forEach((elem, idx) => { - - // Create a single row with all columns - var row = document.createElement('tr'); - var id = 'wifi-' + idx; - row.id = id; - row.addEventListener('click', selectWifi); - row.innerHTML = ``; - row.innerHTML += `${elem.ssid}`; - row.innerHTML += '' + elem.strength + ' dBm'; - if (elem.security) - row.innerHTML += '' + svgLock + ''; - else - row.innerHTML += '' + svgUnlock + ''; - - // Add row to list - list.appendChild(row); - }); - - $("wifi-table").classList.remove("hide"); -} - - -function getParameters() { - $('loader').classList.remove('hide'); - var url = new URL("http://" + `${window.location.hostname}` + "/config.json"); - fetch(url) - .then(response => response.json()) - .then(data => { - Object.keys(data).forEach(function (key) { - if (key.startsWith('logo-name')) { - $('name-logo').innerHTML = data[key]; - delete data[key]; - } - if (key.startsWith('logo-svg')) { - $('svg-logo').innerHTML = data[key]; - delete data[key]; - } - $('loader').classList.add('hide'); - }); - - options = data; - listParameters(options); - - // Read logo from file if present, otherwise use inline svg; - if (options['logo-file-hidden']) { - svgLogo = ''; - $('svg-logo').innerHTML = ''; - $('svg-logo').setAttribute('title', ''); - $('logo-file').setAttribute('type', 'number'); - } - }); -} - - -function createNewBox(cont, lbl) { - var el = document.createElement('div'); - el.setAttribute('id', 'option-box' + cont); - el.classList.add('ctn', 'opt-box', 'hide'); - - var h = document.createElement('h2'); - h.classList.add('heading-2'); - h.innerHTML = lbl; - el.appendChild(h); - - var form = document.createElement('form'); - form.classList.add('form'); - - el.appendChild(form); - $('main-box').appendChild(el); - - // Add new voice in menu and relatvie listener - var lnk = document.createElement('a'); - lnk.setAttribute('id', 'set-opt' + cont); - lnk.setAttribute('data-box', 'option-box' + cont); - lnk.classList.add('a-link'); - lnk.innerHTML = lbl; - lnk.addEventListener('click', switchPage); - - $('nav-link').appendChild(lnk); - return form; -} - -function listParameters(params) { - var el, pBox; - if (!Object.keys(params)[0].startsWith('param-box')) { - params = { 'param-box1': 'Options', ...params }; - options = params; - } - - Object.entries(params).forEach(([key, value], i) => { - - if (key.startsWith('name-logo')) { - $('name-logo').innerHTML = value; - return; - } - - else if (key.startsWith('logo-file')) { - return; - } - - else if (key.startsWith('param-box')) { - pBox = createNewBox(i, value); - return; - } - - else if (key.startsWith('raw-css')) { - var css = document.createElement("style"); - css.innerHTML = value.trim(); - document.body.appendChild(css); - return; - } - - else if (key.startsWith('raw-javascript')) { - var js = document.createElement("script"); - js.innerHTML = value.trim(); - document.body.appendChild(js); - return; - } - - else if (key.startsWith('raw-html')) { - html = value.trim(); - el = document.createElement('div'); - el.setAttribute('id', 'row' + i) - el.style.width = '100%'; - el.innerHTML = html; - pBox.appendChild(el); - } - else { - let val = value; - let lbl = document.createElement('label'); - el = document.createElement('input'); - el.setAttribute('id', key); - el.setAttribute('type', 'text'); - - // Set input property (id, type and value). Check first if is boolean - if (typeof (val) === "boolean") { - el.setAttribute('type', 'checkbox'); - el.classList.add('t-check', 'opt-input'); - el.checked = val; - lbl.classList.add('input-label', 'toggle'); - let dv = document.createElement('div'); - dv.classList.add('toggle-switch'); - let sp = document.createElement('span'); - sp.classList.add('toggle-label'); - sp.textContent = key; - lbl.appendChild(el); - lbl.appendChild(dv); - lbl.appendChild(sp); - pBox.appendChild(lbl); - addInputListener(el); - } - else { - el.value = val; - el.classList.add('opt-input'); - lbl.setAttribute('label-for', key); - lbl.classList.add('input-label'); - lbl.textContent = key; - if (typeof (val) === "number") - el.setAttribute('type', 'number'); - - if (typeof (val) === "object") { - // This is a select/option - if (val.values) { - el = document.createElement('select'); - el.setAttribute('id', key); - val.values.forEach((a) => { - var opt = document.createElement('option'); - opt.textContent = a; - opt.value = a; - el.appendChild(opt); - }) - el.value = val.selected; - pBox.appendChild(el); - } - - // This is a float value - else { - var num = Math.round(val.value * (1 / val.step)) / (1 / val.step); - el.setAttribute('type', 'number'); - el.setAttribute('step', val.step); - el.setAttribute('min', val.min); - el.setAttribute('max', val.max); - el.value = Number(num).toFixed(3); - } - } - addInputListener(el); - var d = document.createElement('div'); - d.classList.add('tf-wrapper'); - d.appendChild(lbl); - d.appendChild(el); - pBox.appendChild(d); - } - } - - if (key.endsWith('-hidden')) { - el.classList.add('hide'); - } - }); -} - -function addInputListener(item) { - // Add event listener to option inputs - - if (item.type === "number") { - item.addEventListener('change', () => { - if (item.getAttribute("step")) { - var obj = {}; - obj.value = Math.round(item.value * (1 / item.step)) / (1 / item.step); - obj.step = item.getAttribute("step"); - obj.min = item.getAttribute("min"); - obj.max = item.getAttribute("max"); - options[item.id] = obj; - } - else - options[item.id] = parseInt(item.value); - }); - return; - } - - if (item.type === "text") { - item.addEventListener('change', () => { - options[item.id] = item.value; - }); - return; - } - - if (item.type === "checkbox") { - item.addEventListener('change', () => { - options[item.id] = item.checked; - }); - return; - } - - if (item.type === 'select-one') { - item.addEventListener('change', (e) => { - options[e.target.id].selected = e.target.value; - }); - return; - } -} - - -function saveParameters() { - var myblob = new Blob([JSON.stringify(options, null, 2)], { - type: 'application/json' - }); - var formData = new FormData(); - formData.append("data", myblob, '/config.json'); - - // POST data using the Fetch API - fetch('/edit', { - method: 'POST', - body: formData - }) - // Handle the server response - .then(response => response.text()) - .then(text => { - openModalMessage('Save options', 'Settings saved successfully on flash memory!

'); - }); - - fetch('/save') - .then(response => response.text()) - .then(text => { - - }) - .catch(error => { - - }); -} - - -function doConnection() { - var formdata = new FormData(); - formdata.append("ssid", $('ssid').value); - formdata.append("password", $('password').value); - formdata.append("persistent", $('persistent').checked); - var requestOptions = { - method: 'POST', - body: formdata, - redirect: 'follow' - }; - - $('loader').classList.remove('hide'); - fetch('/connect', requestOptions) - .then(function (response) { - httpCode = response.status; - return response.text(); - }) - .then(function (text) { - if (httpCode === 200) { - openModalMessage('Connected', 'AWTRTIX will restart now
Your new IP is ' + text); - } - else { - openModalMessage('Error!', '
Error on connection: ' + text + '

'); - } - $('loader').classList.add('hide'); - }); -} - - -function switchPage(el) { - $('top-nav').classList.remove('responsive'); - - // Menu items - document.querySelectorAll("a").forEach(item => { - item.classList.remove('active'); - }); - el.target.classList.add('active'); - - // Box items - document.querySelectorAll(".opt-box").forEach(e => { - e.classList.add('hide'); - }); - $(el.target.getAttribute("data-box")).classList.remove('hide'); - - if (el.target.id != 'set-wifi') { - var fragment = document.createDocumentFragment(); - fragment.appendChild($('btn-box')); - $(el.target.getAttribute("data-box")).appendChild(fragment); - $('btn-box').classList.remove('hide'); - } - else - $('btn-box').classList.add('hide'); -} - - -function showMenu() { - $('top-nav').classList.add('responsive'); -} - -var closeCallback = function () { ; }; - -function openModalMessage(title, msg, fn) { - $('message-title').innerHTML = title; - $('message-body').innerHTML = msg; - $('modal-message').open = true; - $('main-box').style.filter = "blur(3px)"; - if (typeof fn != 'undefined') { - closeCallback = fn; - $('ok-modal').classList.remove('hide'); - } - else - $('ok-modal').classList.add('hide'); -} - -function closeModalMessage(do_cb) { - $('modal-message').open = false; - $('main-box').style.filter = ""; - if (typeof closeCallback != 'undefined' && do_cb) - closeCallback(); -} - - -function restartESP() { - var url = new URL("http://" + `${window.location.hostname}` + "/restart"); - fetch(url) - .then(response => response.text()) - .then(data => { - closeModalMessage(); - openModalMessage('Restart!', '
ESP restarted. Please wait a little and then reload this page.
'); - }); -} - -function uploadLogo() { - var file = $('logo-file').files[0]; - var reader = new FileReader(); - - reader.onload = async () => { - const formData = new FormData(); - formData.append('image', file); - try { - const response = await fetch('/edit', { - method: 'POST', - body: formData, - }); - options = { ...options, 'logo-file-hidden': file.name }; - saveParameters(); - } - catch (error) { - console.error(error); - } - }; - reader.readAsDataURL(file); -} - -// Initializes the app. -$('svg-menu').innerHTML = svgMenu; -$('svg-eye').innerHTML = svgEye; -$('svg-no-eye').innerHTML = svgNoEye; -$('svg-scan').innerHTML = svgScan; -$('svg-connect').innerHTML = svgConnect; -$('svg-save').innerHTML = svgSave; -$('svg-restart').innerHTML = svgRestart; -$('close-modal').innerHTML = svgCloseModal; -$('svg-logo').innerHTML = svgLogo; -$('svg-logo').setAttribute('title', 'Click to upload your logo file'); - -$('hum-btn').addEventListener('click', showMenu); -$('scan-wifi').addEventListener('click', getWiFiList); -$('connect-wifi').addEventListener('click', doConnection); -$('save-params').addEventListener('click', saveParameters); -$('show-hide-password').addEventListener('click', showHidePassword); -$('set-wifi').addEventListener('click', switchPage); -// $('set-opt1').addEventListener('click', switchPage); -$('about').addEventListener('click', switchPage); -$('restart').addEventListener('click', restartESP); - -window.addEventListener('load', getParameters); - -// Enable wifi-connect btn only if password inserted -$('connect-wifi').disabled = true; -$('password').addEventListener('input', (event) => { - if ($('password').value.length === 0) - $('connect-wifi').disabled = true; - else - $('connect-wifi').disabled = false; -}); \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/build/min/all.htm b/lib/webserver/setup-ui/data/build/min/all.htm deleted file mode 100644 index 25e2b411..00000000 --- a/lib/webserver/setup-ui/data/build/min/all.htm +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - AWTRIX Light - - - - - -
-
-
- -

AWTRIX Light

-

-
- -
-
-

Connect to WiFi

-
- - -
-
-
-
-
-
- - -
-
- - - -
-
-
-
- - -
- Scan WiFi networks -
- -
- Connect to SSID -
-
-
- -
-
Loading...
- - - - - - \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/build/min/all.htm.gz b/lib/webserver/setup-ui/data/build/min/all.htm.gz deleted file mode 100644 index 0d1b698af1644e0a329ead6210db617447256878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8405 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 diff --git a/lib/webserver/setup-ui/data/build/min/app.js b/lib/webserver/setup-ui/data/build/min/app.js deleted file mode 100644 index 0fa294d0..00000000 --- a/lib/webserver/setup-ui/data/build/min/app.js +++ /dev/null @@ -1 +0,0 @@ -svgLogo='';const svgMenu='',svgLock='',svgUnlock='',svgScan='',svgConnect='',svgSave='',svgRestart='',svgEye='',svgNoEye='',svgCloseModal='';var options={},$=function(e){return document.getElementById(e)};function showHidePassword(){var e=$("password");openModalMessage("Restart!","
ESP restarted. Please wait a little and then reload this page.
"),"password"===e.type?(e.type="text",$("show-pass").classList.remove("w--current"),$("hide-pass").classList.add("w--current")):(e.type="password",$("show-pass").classList.add("w--current"),$("hide-pass").classList.remove("w--current"))}function getWiFiList(){$("loader").classList.remove("hide");var e=new URL(`http://${window.location.hostname}/scan`);fetch(e).then((e=>e.json())).then((e=>{listWifiNetworks(e),$("loader").classList.add("hide")}))}function selectWifi(e){try{$("select-"+e.target.parentNode.id).checked=!0}catch(t){$(e.target.id).checked=!0}$("ssid").value=this.cells[1].innerHTML,$("ssid-name").innerHTML=this.cells[1].innerHTML,$("password").focus()}function listWifiNetworks(e){const t=document.querySelector("#wifi-list");t.innerHTML="",e.forEach(((e,s)=>{var a=document.createElement("tr"),n="wifi-"+s;a.id=n,a.addEventListener("click",selectWifi),a.innerHTML=``,a.innerHTML+=`${e.ssid}`,a.innerHTML+=''+e.strength+" dBm",e.security?a.innerHTML+=""+svgLock+"":a.innerHTML+=""+svgUnlock+"",t.appendChild(a)})),$("wifi-table").classList.remove("hide")}function getParameters(){$("loader").classList.remove("hide");var e=new URL(`http://${window.location.hostname}/config.json`);fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((function(t){t.startsWith("logo-name")&&($("name-logo").innerHTML=e[t],delete e[t]),t.startsWith("logo-svg")&&($("svg-logo").innerHTML=e[t],delete e[t]),$("loader").classList.add("hide")})),listParameters(options=e),options["logo-file-hidden"]&&(svgLogo="",$("svg-logo").innerHTML='',$("svg-logo").setAttribute("title",""),$("logo-file").setAttribute("type","number"))}))}function createNewBox(e,t){var s=document.createElement("div");s.setAttribute("id","option-box"+e),s.classList.add("ctn","opt-box","hide");var a=document.createElement("h2");a.classList.add("heading-2"),a.innerHTML=t,s.appendChild(a);var n=document.createElement("form");n.classList.add("form"),s.appendChild(n),$("main-box").appendChild(s);var i=document.createElement("a");return i.setAttribute("id","set-opt"+e),i.setAttribute("data-box","option-box"+e),i.classList.add("a-link"),i.innerHTML=t,i.addEventListener("click",switchPage),$("nav-link").appendChild(i),n}function listParameters(e){var t,s;Object.keys(e)[0].startsWith("param-box")||(e={"param-box1":"Options",...e},options=e),Object.entries(e).forEach((([e,a],n)=>{if(e.startsWith("name-logo"))$("name-logo").innerHTML=a;else if(!e.startsWith("logo-file"))if(e.startsWith("param-box"))s=createNewBox(n,a);else{if(e.startsWith("raw-css")){var i=document.createElement("style");return i.innerHTML=a.trim(),void document.body.appendChild(i)}if(e.startsWith("raw-javascript")){var o=document.createElement("script");return o.innerHTML=a.trim(),void document.body.appendChild(o)}if(e.startsWith("raw-html"))html=a.trim(),(t=document.createElement("div")).setAttribute("id","row"+n),t.style.width="100%",t.innerHTML=html,s.appendChild(t);else{let n=a,i=document.createElement("label");if((t=document.createElement("input")).setAttribute("id",e),t.setAttribute("type","text"),"boolean"==typeof n){t.setAttribute("type","checkbox"),t.classList.add("t-check","opt-input"),t.checked=n,i.classList.add("input-label","toggle");let a=document.createElement("div");a.classList.add("toggle-switch");let o=document.createElement("span");o.classList.add("toggle-label"),o.textContent=e,i.appendChild(t),i.appendChild(a),i.appendChild(o),s.appendChild(i),addInputListener(t)}else{if(t.value=n,t.classList.add("opt-input"),i.setAttribute("label-for",e),i.classList.add("input-label"),i.textContent=e,"number"==typeof n&&t.setAttribute("type","number"),"object"==typeof n)if(n.values)(t=document.createElement("select")).setAttribute("id",e),n.values.forEach((e=>{var s=document.createElement("option");s.textContent=e,s.value=e,t.appendChild(s)})),t.value=n.selected,s.appendChild(t);else{var d=Math.round(n.value*(1/n.step))/(1/n.step);t.setAttribute("type","number"),t.setAttribute("step",n.step),t.setAttribute("min",n.min),t.setAttribute("max",n.max),t.value=Number(d).toFixed(3)}addInputListener(t);var r=document.createElement("div");r.classList.add("tf-wrapper"),r.appendChild(i),r.appendChild(t),s.appendChild(r)}}e.endsWith("-hidden")&&t.classList.add("hide")}}))}function addInputListener(e){"number"!==e.type?"text"!==e.type?"checkbox"!==e.type?"select-one"!==e.type||e.addEventListener("change",(e=>{options[e.target.id].selected=e.target.value})):e.addEventListener("change",(()=>{options[e.id]=e.checked})):e.addEventListener("change",(()=>{options[e.id]=e.value})):e.addEventListener("change",(()=>{if(e.getAttribute("step")){var t={};t.value=Math.round(e.value*(1/e.step))/(1/e.step),t.step=e.getAttribute("step"),t.min=e.getAttribute("min"),t.max=e.getAttribute("max"),options[e.id]=t}else options[e.id]=parseInt(e.value)}))}function saveParameters(){var e=new Blob([JSON.stringify(options,null,2)],{type:"application/json"}),t=new FormData;t.append("data",e,"/config.json"),fetch("/edit",{method:"POST",body:t}).then((e=>e.text())).then((e=>{openModalMessage("Save options","Settings saved successfully on flash memory!

")})),fetch("/save").then((e=>e.text())).then((e=>{})).catch((e=>{}))}function doConnection(){var e=new FormData;e.append("ssid",$("ssid").value),e.append("password",$("password").value),e.append("persistent",$("persistent").checked);var t={method:"POST",body:e,redirect:"follow"};$("loader").classList.remove("hide"),fetch("/connect",t).then((function(e){return httpCode=e.status,e.text()})).then((function(e){200===httpCode?openModalMessage("Connected","AWTRTIX will restart now
Your new IP is "+e):openModalMessage("Error!","
Error on connection: "+e+"

"),$("loader").classList.add("hide")}))}function switchPage(e){if($("top-nav").classList.remove("responsive"),document.querySelectorAll("a").forEach((e=>{e.classList.remove("active")})),e.target.classList.add("active"),document.querySelectorAll(".opt-box").forEach((e=>{e.classList.add("hide")})),$(e.target.getAttribute("data-box")).classList.remove("hide"),"set-wifi"!=e.target.id){var t=document.createDocumentFragment();t.appendChild($("btn-box")),$(e.target.getAttribute("data-box")).appendChild(t),$("btn-box").classList.remove("hide")}else $("btn-box").classList.add("hide")}function showMenu(){$("top-nav").classList.add("responsive")}var closeCallback=function(){};function openModalMessage(e,t,s){$("message-title").innerHTML=e,$("message-body").innerHTML=t,$("modal-message").open=!0,$("main-box").style.filter="blur(3px)",void 0!==s?(closeCallback=s,$("ok-modal").classList.remove("hide")):$("ok-modal").classList.add("hide")}function closeModalMessage(e){$("modal-message").open=!1,$("main-box").style.filter="",void 0!==closeCallback&&e&&closeCallback()}function restartESP(){var e=new URL(`http://${window.location.hostname}/restart`);fetch(e).then((e=>e.text())).then((e=>{closeModalMessage(),openModalMessage("Restart!","
ESP restarted. Please wait a little and then reload this page.
")}))}function uploadLogo(){var e=$("logo-file").files[0],t=new FileReader;t.onload=async()=>{const t=new FormData;t.append("image",e);try{await fetch("/edit",{method:"POST",body:t});options={...options,"logo-file-hidden":e.name},saveParameters()}catch(e){console.error(e)}},t.readAsDataURL(e)}$("svg-menu").innerHTML=svgMenu,$("svg-eye").innerHTML=svgEye,$("svg-no-eye").innerHTML=svgNoEye,$("svg-scan").innerHTML=svgScan,$("svg-connect").innerHTML=svgConnect,$("svg-save").innerHTML=svgSave,$("svg-restart").innerHTML=svgRestart,$("close-modal").innerHTML=svgCloseModal,$("svg-logo").innerHTML=svgLogo,$("svg-logo").setAttribute("title","Click to upload your logo file"),$("hum-btn").addEventListener("click",showMenu),$("scan-wifi").addEventListener("click",getWiFiList),$("connect-wifi").addEventListener("click",doConnection),$("save-params").addEventListener("click",saveParameters),$("show-hide-password").addEventListener("click",showHidePassword),$("set-wifi").addEventListener("click",switchPage),$("about").addEventListener("click",switchPage),$("restart").addEventListener("click",restartESP),window.addEventListener("load",getParameters),$("connect-wifi").disabled=!0,$("password").addEventListener("input",(e=>{0===$("password").value.length?$("connect-wifi").disabled=!0:$("connect-wifi").disabled=!1})); \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/build/min/style.css b/lib/webserver/setup-ui/data/build/min/style.css deleted file mode 100644 index cb5c39f2..00000000 --- a/lib/webserver/setup-ui/data/build/min/style.css +++ /dev/null @@ -1 +0,0 @@ -.inputfile{height:10px;opacity:0;overflow:hidden;position:absolute;width:10px;z-index:-1}.loader,.loader:after,.loader:before{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:load7 1.8s ease-in-out infinite;animation:load7 1.8s ease-in-out infinite;border-radius:50%;height:2em;width:2em}.loader{-webkit-animation-delay:-.16s;animation-delay:-.16s;color:#333;font-size:10px;margin-left:auto;margin-right:auto;position:relative;text-indent:-9999em;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);z-index:999}.loader:after,.loader:before{content:"";position:absolute;top:0}.loader:before{-webkit-animation-delay:-.32s;animation-delay:-.32s;left:-4.5em}.loader:after{left:4.5em}@-webkit-keyframes load7{0%,80%,to{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}@keyframes load7{0%,80%,to{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}tr:hover{filter:brightness(85%)}.d-modal{background-color:hsla(0,0%,100%,.95);border:1px solid #3333336e;border-radius:10px;box-shadow:0 3px 8px rgba(0,0,0,.24);flex-direction:column;left:50%;max-height:40vh;max-width:90%;text-align:left;top:40%;transform:translate(-50%,-50%);width:25em;z-index:999}.d-modal,.d-modal-close{display:flex;position:absolute}.d-modal-close{align-items:center;color:#111827;cursor:pointer;height:4.5em;justify-content:center;right:0;top:0;width:4.5em}.d-modal-title{color:#111827;padding:1.5em 2em;position:relative;width:calc(100% - 4.5em)}.d-modal-content{border-top:1px solid #e0e0e0;overflow:auto;padding:2em}.topnav{background-color:#333;border-radius:5px;float:right;height:28px,;overflow:hidden;width:fit-content}.topnav a{color:#f2f2f2;display:block;float:left;font-size:16px;padding:5px 10px;text-align:center;text-decoration:none}.topnav a:hover{background-color:#ddd;color:#000}.topnav a.active{background-color:#56c080;color:#fff}.topnav .icon{display:none}*{box-sizing:border-box}.logo{width:100%}.lbl-wifi{padding:0;text-align:right}html{font-family:sans-serif}details,header,main,summary{display:block}.table{border-collapse:collapse;border-spacing:0;margin:auto;width:90%}a{background-color:transparent}a:active,a:hover{outline:0}b{font-weight:700}h1{font-size:38px}h2{font-size:24px}hr{padding:0}.input-label{background-color:#fff;border:1px solid #dcdce5;border-radius:6px;bottom:-7px;color:#015293;display:inline-block;font-size:13.5px;font-weight:500;left:8px;line-height:17px;margin-bottom:0;padding-left:6px;padding-right:7px;position:relative;z-index:2}input:-webkit-autofill,input:-webkit-autofill:active,input:-webkit-autofill:focus,input:-webkit-autofill:hover{-webkit-box-shadow:inset 0 0 0 30px #fff!important}input[type=checkbox]{box-sizing:border-box;padding:0}input[type=number],input[type=password],input[type=text],select{border:1px solid #ccc;border-radius:6px;box-shadow:0 1px 2px 0 rgba(220,220,230,.5);font-size:16px;height:40px;padding-left:20px;padding-top:10px;transition:border-color .2s ease,box-shadow .2s ease;width:100%}input::placeholder{color:#5e5e5e}input:hover{border-color:rgba(0,0,0,.8);box-shadow:0 1px 4px 0 rgba(220,220,229,.9)}input:focus,select:focus{border-color:#3898ec;outline:0}.ctn:after,.ctn:before{content:" ";display:table;grid-column-end:2;grid-column-start:1;grid-row-end:2;grid-row-start:1}.ctn,.ctn:after{clear:both}.ctn{align-content:space-around;align-items:center;background-color:hsla(0,0%,100%,.8);border:1px solid #3333336e;border-radius:10px;box-shadow:0 3px 8px rgba(0,0,0,.24);display:block;flex-direction:row;flex-wrap:wrap;justify-content:center;margin:10px auto;max-width:940px;padding:10px 40px}footer{font-size:12px;margin:40px;text-align:center}#about{color:#d3d3d3}.body{background-clip:border-box;background-color:#edf0f3;border-radius:10px;padding-left:20px;padding-right:20px}.title{align-items:center;display:flex;flex:1;justify-content:center}.heading-2{font-weight:400;text-align:center}.form,.heading-2{padding-left:20px;padding-right:20px}.form{position:static}.btn,button{background-color:#3898ec;border:0;border-radius:5px;color:#fff;cursor:pointer;display:inline-flex;justify-content:center;min-width:40%;padding:10px 15px}.btn:hover,button:hover{filter:brightness(85%)}.btn-bar{grid-column-gap:30px;grid-row-gap:20px;align-content:space-around;align-items:stretch;display:flex;flex-wrap:wrap;justify-content:right;margin-top:20px;padding:20px}.tf-wrapper{align-items:flex-start;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:column;margin-bottom:12px;position:relative;width:100%}.show-hide{background-color:#fff;display:flex;font-size:13.5px;max-width:100%}.show-hide-wrap{bottom:auto;cursor:pointer;left:auto;position:absolute;right:2%;top:40%;z-index:4}.svg{display:flex;margin-right:10px;width:20px}.svg-e{margin-top:5px}.heading{margin-left:10px;margin-right:10px}.hide,.show-hide.w--current{display:none}.toggle{cursor:pointer;display:inline-block;left:0;margin:0 0 12px;padding:5px;width:100%}.toggle-switch{background:#ccc;border-radius:16px;display:inline-block;height:32px;position:relative;transition:background .25s;vertical-align:middle;width:58px}.toggle-switch:after,.toggle-switch:before{content:""}.toggle-switch:before{background:linear-gradient(180deg,#fff 0,#eee);border-radius:50%;box-shadow:0 0 0 1px rgba(0,0,0,.25);display:block;height:24px;left:4px;position:absolute;top:4px;transition:left .25s;width:24px}.toggle:hover .toggle-switch:before{background:linear-gradient(180deg,#fff 0,#fff);box-shadow:0 0 0 1px rgba(0,0,0,.5)}.t-check:checked+.toggle-switch{background:#56c080}.t-check:checked+.toggle-switch:before{left:30px}.t-check{position:absolute;visibility:hidden}.toggle-label{margin-left:5px;position:relative;top:2px}@media screen and (max-width:991px){.ctn{grid-column-gap:10px;grid-row-gap:10px;max-width:728px;max-width:95%;object-fit:contain;overflow:visible;position:relative}.ctn,.wifi-connect{padding-left:20px;padding-right:20px}}@media screen and (max-width:767px){.wifi-connect{padding-left:10px;padding-right:10px}}@media screen and (max-width:608px){.btn-bar{flex-direction:column;margin-top:20px}.topnav{margin-bottom:5px;width:-webkit-fill-available}.topnav a{padding:5px 20px}.topnav a:not(.active){display:none}.topnav a.icon{display:block;float:right}.topnav a:hover{background-color:hsla(0,0%,87%,0);color:#5a5a5a}.topnav.responsive{position:relative}.topnav.responsive .icon{position:absolute;right:0;top:0}.topnav.responsive a{display:block;float:none;text-align:left}.hide-tiny{display:none}}@media screen and (max-width:479px){h1{font-size:30px}.body{padding-left:2px;padding-right:2px}.heading-2{margin-top:10px}.form,.heading-2{padding-left:0;padding-right:0}.ctn{max-width:100%;padding:0 10px}} \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/build/minify.js b/lib/webserver/setup-ui/data/build/minify.js deleted file mode 100644 index 136edbfa..00000000 --- a/lib/webserver/setup-ui/data/build/minify.js +++ /dev/null @@ -1,71 +0,0 @@ -// Finalize Nodejs Script -// 1 - Append JS in HTML Document -// 2 - Gzip HTML -// 3 - Covert to Raw Bytes -// 4 - ( Save to File: webpage.h ) in dist Folder - -const fs = require('fs'); -const minify = require('@node-minify/core'); -const terser = require('@node-minify/terser'); -const cssnano = require('@node-minify/cssnano'); -// const csso = require('@node-minify/csso'); -// const uglifyjs = require('@node-minify/uglify-js'); -// const gcc = require('@node-minify/google-closure-compiler'); -// const htmlMinifier = require('@node-minify/html-minifier'); - -const converter = require('./stringConverter'); - -minify({ - compressor: terser, - input: '../app.js', - output: './min/app.js', - sync: true, - callback: function (err, min) { if (err) console.log(err); } -}); - -minify({ - compressor: cssnano, - input: '../style.css', - output: './min/style.css', - sync: true, - callback: function (err, min) { if (err) console.log(err); } -}); - - -let html = fs.readFileSync('../setup.htm').toString(); -let css = fs.readFileSync('./min/style.css'); -let appjs = fs.readFileSync('./min/app.js'); -console.log(css.length); -console.log(appjs.length); - -html = html.replace('', ``); -html = html.replace('', ``); - -// minify({ -// compressor: htmlMinifier, -// content: html -// }).then(function (min) { -// console.log('html min'); -// }); - -fs.writeFile('./min/all.htm', html, function (err) { - if (err) return console.log(err); -}); - -const { createGzip } = require('node:zlib'); -const { pipeline } = require('node:stream'); -const { createReadStream, createWriteStream } = require('node:fs'); - -const gzip = createGzip(); -const source = createReadStream('./min/all.htm'); -var destination = createWriteStream('./min/all.htm.gz'); - -pipeline(source, gzip, destination, (err) => { - if (err) { - console.error('An error occurred:', err); - process.exitCode = 1; - } - - var c_array = converter.toString(fs.readFileSync('./min/all.htm.gz'), 16); - fs.writeFileSync('setup_htm.h', c_array, 'utf8'); -}) \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/build/package-lock.json b/lib/webserver/setup-ui/data/build/package-lock.json deleted file mode 100644 index d514bc11..00000000 --- a/lib/webserver/setup-ui/data/build/package-lock.json +++ /dev/null @@ -1,1524 +0,0 @@ -{ - "name": "build", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "build", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@gfx/zopfli": "^1.0.15", - "@node-minify/core": "^7.1.0", - "@node-minify/cssnano": "^7.1.0", - "@node-minify/csso": "^7.1.0", - "@node-minify/html-minifier": "^7.1.0", - "@node-minify/terser": "^7.1.0" - } - }, - "node_modules/@gfx/zopfli": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@gfx/zopfli/-/zopfli-1.0.15.tgz", - "integrity": "sha512-7mBgpi7UD82fsff5ThQKet0uBTl4BYerQuc+/qA1ELTwWEiIedRTcD3JgiUu9wwZ2kytW8JOb165rSdAt8PfcQ==", - "dependencies": { - "base64-js": "^1.3.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@node-minify/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/core/-/core-7.1.0.tgz", - "integrity": "sha512-0lFnw0m4mokyYv3R0Dp83cC3fMHDvYERdncpc8I5KcHiB7kHppxeupRXFEJTkjdxzvryA3OgF1cWNlvtbX1Biw==", - "dependencies": { - "@node-minify/utils": "^7.1.0", - "globby": "11.0.4", - "mkdirp": "1.0.4" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-minify/cssnano": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/cssnano/-/cssnano-7.1.0.tgz", - "integrity": "sha512-v7aKK1Zt6QfPnwC+chAPmX/ViybCYEnb3GWC0O8P12CEt/achN4Fae4WqSNjiboVQZXyEslZkUOYBlWD5R5xMg==", - "dependencies": { - "@node-minify/utils": "^7.1.0", - "cssnano": "^5.0.0", - "postcss": "8.4.19" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-minify/csso": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/csso/-/csso-7.1.0.tgz", - "integrity": "sha512-Lu9RwHsMTCj7YicN+3sZSMaYTK6oJ+sW0J/t3jLMZ7Vf+5IFyN9JCMjpxaLyyaqtUew+61F5IW/DAwF3JbRUfg==", - "dependencies": { - "@node-minify/utils": "^7.1.0", - "csso": "5.0.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-minify/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@node-minify/csso/node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@node-minify/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" - }, - "node_modules/@node-minify/html-minifier": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/html-minifier/-/html-minifier-7.1.0.tgz", - "integrity": "sha512-A5cd2GjS6mlEAzLFBpH61oAMhLu6lWF/7gQ5nQXasQMwAoV8hTWfP+P0DqdFtaFblT6t/mOnqbc+8ZWdNJlQ2A==", - "dependencies": { - "@node-minify/utils": "^7.1.0", - "html-minifier": "4.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-minify/terser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/terser/-/terser-7.1.0.tgz", - "integrity": "sha512-VDEa19CSDE8vlE03Feblre5jC5zJcZHbQ6lwCKHy5hrgCLg6PkWECmaYmpMSeIlZ5m6xr1aUfszDxoJHdKKNPg==", - "dependencies": { - "@node-minify/utils": "^7.1.0", - "terser": "5.15.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-minify/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@node-minify/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-Sjlwlujvzm06tg+wRGgOpni2oeG1GzyEWCNLLBPSJ5rGwcJlBEkvzg6DHGJ9nQ2Emj15Hkw/ITSwQbLvISeNBg==", - "dependencies": { - "gzip-size": "6.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" - }, - "node_modules/css-declaration-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", - "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.14.tgz", - "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==", - "dependencies": { - "cssnano-preset-default": "^5.2.13", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.13", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz", - "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==", - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.0", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.3", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.1", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.288", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.288.tgz", - "integrity": "sha512-8s9aJf3YiokIrR+HOQzNOGmEHFXVUQzXM/JaViVvKdCkNUjS+lEa/uT7xw3nDVG/IgfxiIwUGkwJ6AR1pTpYsQ==" - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-minifier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", - "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", - "dependencies": { - "camel-case": "^3.0.0", - "clean-css": "^4.2.1", - "commander": "^2.19.0", - "he": "^1.2.0", - "param-case": "^2.1.1", - "relateurl": "^0.2.7", - "uglify-js": "^3.5.1" - }, - "bin": { - "html-minifier": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/html-minifier/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==" - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", - "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", - "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz", - "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz", - "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" - }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - } - } -} diff --git a/lib/webserver/setup-ui/data/build/package.json b/lib/webserver/setup-ui/data/build/package.json deleted file mode 100644 index 2c7bf9d4..00000000 --- a/lib/webserver/setup-ui/data/build/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "dependencies": { - "@gfx/zopfli": "^1.0.15", - "@node-minify/core": "^7.1.0", - "@node-minify/cssnano": "^7.1.0", - "@node-minify/csso": "^7.1.0", - "@node-minify/html-minifier": "^7.1.0", - "@node-minify/terser": "^7.1.0" - }, - "name": "build", - "description": "If you want customize **/setup** webpage (headers, logo etc etc): * edit the source files as your needs (setup.htm, app.js, style.css) * open a terminal in *build* folder and run `npm i` to install all nodejs modules needed * run `node finalize.js` * overwrite the content of *setup_htm.h* in src folder", - "version": "1.0.0", - "main": "minify.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC" -} diff --git a/lib/webserver/setup-ui/data/build/readme.md b/lib/webserver/setup-ui/data/build/readme.md deleted file mode 100644 index f2395847..00000000 --- a/lib/webserver/setup-ui/data/build/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -If you want customize **/setup** webpage (headers, logo etc etc): -* edit the source files as your needs (setup.htm, app.js, style.css) -* open a terminal in *build* folder and run `npm i` to install all nodejs modules needed -* run `node minimize.js` -* overwrite the content of *setup_htm.h* in src folder with the new generated file diff --git a/lib/webserver/setup-ui/data/build/stringConverter.js b/lib/webserver/setup-ui/data/build/stringConverter.js deleted file mode 100644 index 5c732f33..00000000 --- a/lib/webserver/setup-ui/data/build/stringConverter.js +++ /dev/null @@ -1,48 +0,0 @@ -var stringConverter = { - convertByte: function (oneByte, bytesPerPixel) { - var stringByte = '0x' + oneByte.toString(16).padStart(bytesPerPixel * 2, '0'); - return stringByte; - }, - convert: function (dataLength, bytesPerPixel, multiLine, colNumber, data) { - var resultString = ''; - for (var i = 0; i < dataLength; i++) { - var stringByte = ''; - // need to use bigint, so we can use 32bit integers (4byte per pixel) - let combinedByte = BigInt("0b00000000000000000000000000000000"); - for (let j = 0; j < bytesPerPixel; j++) { - let pixelByte = BigInt(data[(i * bytesPerPixel) + j]); - if (j != 0) { - combinedByte = combinedByte << BigInt(8); - } - combinedByte = combinedByte | pixelByte; - } - stringByte = this.convertByte(combinedByte, bytesPerPixel) + ', '; - if (multiLine && ((i + 1) % colNumber == 0)) { - stringByte += '\n '; - } - resultString += stringByte; - } - resultString = resultString.substr(0, resultString.lastIndexOf(',')).trim(); - // add the array definition - return resultString; - } -}; - - -module.exports = { - - toString : function(data, colNum) { - console.log('Converting data to string'); - - var dataLength = data.byteLength; - console.log('actualDataLength: ' + dataLength); - - var resultString = '#define SETUP_HTML_SIZE '; - resultString += dataLength + '\n' - resultString += 'const char SETUP_HTML[] PROGMEM = {\n '; - resultString += stringConverter.convert(dataLength, 1, true, 16, data); - resultString += '\n};'; - return resultString; - } - -} diff --git a/lib/webserver/setup-ui/data/package-lock.json b/lib/webserver/setup-ui/data/package-lock.json deleted file mode 100644 index a7f795bd..00000000 --- a/lib/webserver/setup-ui/data/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "data", - "lockfileVersion": 2, - "requires": true, - "packages": {} -} diff --git a/lib/webserver/setup-ui/data/setup.htm b/lib/webserver/setup-ui/data/setup.htm deleted file mode 100644 index 572b9371..00000000 --- a/lib/webserver/setup-ui/data/setup.htm +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - AWTRIX Light - - - - - -
-
-
- -

AWTRIX Light

-

-
- -
-
-

Connect to WiFi

-
- - -
-
-
-
-
-
- - -
-
- - - -
-
-
-
- - -
- Scan WiFi networks -
- -
- Connect to SSID -
-
-
- -
-
Loading...
- - - - - - \ No newline at end of file diff --git a/lib/webserver/setup-ui/data/style.css b/lib/webserver/setup-ui/data/style.css deleted file mode 100644 index 26573ddb..00000000 --- a/lib/webserver/setup-ui/data/style.css +++ /dev/null @@ -1,597 +0,0 @@ -.inputfile { - width: 10px; - height: 10px; - opacity: 0; - overflow: hidden; - position: absolute; - z-index: -1; -} - -.loader, -.loader:before, -.loader:after { - border-radius: 50%; - width: 2em; - height: 2em; - -webkit-animation-fill-mode: both; - animation-fill-mode: both; - -webkit-animation: load7 1.8s infinite ease-in-out; - animation: load7 1.8s infinite ease-in-out; -} - -.loader { - color: #333; - font-size: 10px; - margin-left: auto; - margin-right: auto; - position: relative; - text-indent: -9999em; - z-index: 999; - -webkit-transform: translateZ(0); - -ms-transform: translateZ(0); - transform: translateZ(0); - -webkit-animation-delay: -0.16s; - animation-delay: -0.16s; -} - -.loader:before, -.loader:after { - content: ''; - position: absolute; - top: 0; -} - -.loader:before { - left: -4.5em; - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; -} - -.loader:after { - left: 4.5em; -} - -@-webkit-keyframes load7 { - - 0%, - 80%, - 100% { - box-shadow: 0 2.5em 0 -1.3em; - } - - 40% { - box-shadow: 0 2.5em 0 0; - } -} - -@keyframes load7 { - - 0%, - 80%, - 100% { - box-shadow: 0 2.5em 0 -1.3em; - } - - 40% { - box-shadow: 0 2.5em 0 0; - } -} - -tr:hover { - filter: brightness(85%); -} - -.d-modal { - border-radius: 10px; - border-style: solid; - border-width: 1px; - border-color: #3333336e; - background-color: hsla(0, 0%, 100%, 0.95); - box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; - left: 50%; - max-width: 90%; - position: absolute; - top: 40%; - transform: translate(-50%, -50%); - width: 25em; - text-align: left; - max-height: 40vh; - display: flex; - flex-direction: column; - z-index: 999; -} - -.d-modal-close { - cursor: pointer; - align-items: center; - color: #111827; - display: flex; - height: 4.5em; - justify-content: center; - position: absolute; - right: 0; - top: 0; - width: 4.5em; -} - -.d-modal-title { - color: #111827; - padding: 1.5em 2em; - position: relative; - width: calc(100% - 4.5em); -} - -.d-modal-content { - border-top: 1px solid #e0e0e0; - padding: 2em; - overflow: auto; -} - -.topnav { - background-color: #333; - overflow: hidden; - width: fit-content; - float: right; - border-radius: 5px; - height: 28px, ; -} - -.topnav a { - float: left; - display: block; - color: #f2f2f2; - text-align: center; - padding: 5px 10px; - text-decoration: none; - font-size: 16px; -} - -.topnav a:hover { - background-color: #ddd; - color: black; -} - -.topnav a.active { - background-color: #56c080; - color: white; -} - -.topnav .icon { - display: none; -} - -* { - box-sizing: border-box; -} - -.logo { - width: 100%; -} - -.lbl-wifi { - text-align: right; - padding: 0 -} - -html { - font-family: sans-serif; -} - -details, -header, -main, -summary { - display: block; -} - -.table { - width: 90%; - margin: auto; - border-collapse: collapse; - border-spacing: 0; -} - -a { - background-color: transparent; -} - -a:active, -a:hover { - outline: 0; -} - -b { - font-weight: 700; -} - -h1 { - font-size: 38px; -} - -h2 { - font-size: 24px; -} - -hr { - padding: 0; -} - -.input-label { - color: #015293; - position: relative; - left: 8px; - bottom: -7px; - z-index: 2; - display: inline-block; - margin-bottom: 0; - padding-right: 7px; - padding-left: 6px; - border-style: solid; - border-width: 1px; - border-color: #dcdce5; - border-radius: 6px; - background-color: #fff; - font-size: 13.5px; - line-height: 17px; - font-weight: 500; -} - -input:-webkit-autofill, -input:-webkit-autofill:hover, -input:-webkit-autofill:focus, -input:-webkit-autofill:active { - -webkit-box-shadow: 0 0 0 30px #fff inset !important; -} - -input[type='checkbox'] { - box-sizing: border-box; - padding: 0; -} - -input[type='text'], -input[type='number'], -input[type='password'], -select { - height: 40px; - width: 100%; - padding-top: 10px; - padding-left: 20px; - border: 1px solid #ccc; - border-radius: 6px; - box-shadow: 0 1px 2px 0 rgba(220, 220, 230, 0.5); - transition: border-color 200ms ease, box-shadow 200ms ease; - font-size: 16px; -} - -input::placeholder { - color: #5e5e5e; -} - -input:hover { - border-color: rgba(0, 0, 0, 0.8); - box-shadow: 0 1px 4px 0 rgba(220, 220, 229, 0.9); -} - -input:focus, -select:focus { - border-color: #3898EC; - outline: 0; -} - -.ctn:before, -.ctn:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} - -.ctn:after { - clear: both; -} - -.ctn { - display: block; - max-width: 940px; - margin: 10px auto 10px auto; - padding: 10px 40px; - clear: both; - flex-direction: row; - justify-content: center; - flex-wrap: wrap; - align-items: center; - align-content: space-around; - border-radius: 10px; - border-style: solid; - border-width: 1px; - border-color: #3333336e; - background-color: hsla(0, 0%, 100%, 0.8); - box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; -} - -footer { - text-align: center; - font-size: 12px; - margin: 40px -} - -#about { - color: lightgray -} - -.body { - padding-right: 20px; - padding-left: 20px; - border-radius: 10px; - background-color: #edf0f3; - background-clip: border-box; -} - -.title { - display: flex; - justify-content: center; - align-items: center; - flex: 1; -} - -.heading-2 { - padding-right: 20px; - padding-left: 20px; - font-weight: 400; - text-align: center; -} - -.form { - position: static; - padding-right: 20px; - padding-left: 20px; -} - -button, -.btn { - display: inline-flex; - padding: 10px 15px; - background-color: #3898EC; - color: #fff; - border: 0; - cursor: pointer; - min-width: 40%; - border-radius: 5px; - justify-content: center; -} - -button:hover, -.btn:hover { - filter: brightness(85%); -} - -.btn-bar { - display: flex; - margin-top: 20px; - padding: 20px; - justify-content: right; - flex-wrap: wrap; - align-items: stretch; - align-content: space-around; - grid-column-gap: 30px; - grid-row-gap: 20px; -} - -.tf-wrapper { - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - width: 100%; - margin-bottom: 12px; - flex-direction: column; - align-items: flex-start; -} - -.show-hide { - max-width: 100%; - display: flex; - background-color: #fff; - font-size: 13.5px; -} - -.show-hide-wrap { - position: absolute; - left: auto; - top: 40%; - right: 2%; - bottom: auto; - z-index: 4; - cursor: pointer; -} - -.svg { - display: flex; - width: 20px; - margin-right: 10px; -} - -.svg-e { - margin-top: 5px; -} - -.heading { - margin-right: 10px; - margin-left: 10px; -} - -.hide, -.show-hide.w--current { - display: none; -} - -.toggle { - cursor: pointer; - display: inline-block; - margin: 0 0 12px 0; - left: 0px; - padding: 5px; - width: 100% -} - -.toggle-switch { - display: inline-block; - background: #ccc; - border-radius: 16px; - width: 58px; - height: 32px; - position: relative; - vertical-align: middle; - transition: background .25s; -} - -.toggle-switch:before, -.toggle-switch:after { - content: ""; -} - -.toggle-switch:before { - display: block; - background: linear-gradient(to bottom, #fff 0%, #eee 100%); - border-radius: 50%; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); - width: 24px; - height: 24px; - position: absolute; - top: 4px; - left: 4px; - transition: left .25s; -} - -.toggle:hover .toggle-switch:before { - background: linear-gradient(to bottom, #fff 0%, #fff 100%); - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5); -} - -.t-check:checked+.toggle-switch { - background: #56c080; -} - -.t-check:checked+.toggle-switch:before { - left: 30px; -} - -.t-check { - position: absolute; - visibility: hidden; -} - -.toggle-label { - margin-left: 5px; - position: relative; - top: 2px; -} - -@media screen and (max-width: 991px) { - .ctn { - max-width: 728px; - } - - .ctn { - position: relative; - overflow: visible; - max-width: 95%; - padding-right: 20px; - padding-left: 20px; - grid-column-gap: 10px; - grid-row-gap: 10px; - object-fit: contain; - } - - .wifi-connect { - padding-right: 20px; - padding-left: 20px; - } -} - -@media screen and (max-width: 767px) { - .wifi-connect { - padding-right: 10px; - padding-left: 10px; - } -} - -@media screen and (max-width: 608px) { - .btn-bar { - margin-top: 20px; - flex-direction: column; - } - - .topnav { - margin-bottom: 5px; - width: -webkit-fill-available - } - - .topnav a { - padding: 5px 20px; - } - - .topnav a:not(.active) { - display: none; - } - - .topnav a.icon { - float: right; - display: block; - } - - .topnav a:hover { - background-color: rgba(221, 221, 221, 0); - color: rgb(90, 90, 90); - } - - .topnav.responsive { - position: relative; - } - - .topnav.responsive .icon { - position: absolute; - right: 0; - top: 0; - } - - .topnav.responsive a { - float: none; - display: block; - text-align: left; - } - - .hide-tiny { - display: none; - } -} - -@media screen and (max-width: 479px) { - h1 { - font-size: 30px; - } - - .body { - padding-right: 2px; - padding-left: 2px; - } - - .heading-2 { - margin-top: 10px; - padding-right: 0; - padding-left: 0; - } - - .form { - padding-right: 0; - padding-left: 0; - } - - .ctn { - max-width: 100%; - padding: 0 10px 0 10px; - } -} \ No newline at end of file diff --git a/lib/webserver/setup-ui/extras.zip b/lib/webserver/setup-ui/extras.zip deleted file mode 100644 index dbb2494bcc2ea634d6f30f7c634836ff562426c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8449 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 YJ*mjQ`=>WJIK+Q<;2$#5{Fn8=03TRbVE_OC diff --git a/lib/webserver/setup-ui/extras/edit.htm b/lib/webserver/setup-ui/extras/edit.htm deleted file mode 100644 index d4eb09e1..00000000 --- a/lib/webserver/setup-ui/extras/edit.htm +++ /dev/null @@ -1,307 +0,0 @@ - - -File manager - - - - - - - -
-
- -

-
Loading...
-
\ No newline at end of file diff --git a/lib/webserver/setup-ui/extras/edit.htm.gz b/lib/webserver/setup-ui/extras/edit.htm.gz deleted file mode 100644 index 8f86390f8c0698a31da37f988045ed1c5deee10b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6553 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 L9o4tBu3G>Av`_X} diff --git a/lib/webserver/setup-ui/extras/edit_htm.h b/lib/webserver/setup-ui/extras/edit_htm.h deleted file mode 100644 index 0ea215fd..00000000 --- a/lib/webserver/setup-ui/extras/edit_htm.h +++ /dev/null @@ -1,4 +0,0 @@ -// WARNING: Auto-generated file. Please do not modify by hand. -// This file is an embeddable version of the gzipped index.htm file. -// To update it, please rerun the `reduce_index.sh` script located in the `extras` subfolder -// then recompile the sketch after each change to the `index.html` file. diff --git a/lib/webserver/setup-ui/extras/feathericons.png b/lib/webserver/setup-ui/extras/feathericons.png deleted file mode 100644 index 5bb2cf63dcdc6f9c0a5309c5823652117e5bdd73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1558 zcmeAS@N?(olHy`uVBq!ia0vp^0zkZggBeH~J(p1fQY`6?zK#qG8~eHcB(gFvFf#=B zgt!95^-OK_&1{V<9W3l!tsOnAoje>I96UWey}iACeSQ7?{at;6JpDs`f+K>0g2KYW zf+FG~A|hg9V&mfC;^X5(qZ7ko5+mbMlQMFXGxD;5ASWj`H#Z*$N-7IVD{C5CYn$3y zT3XtGpsTO5cVhpP8PjIZn>lml+_`fXFI%}}`KomrH?7~WdBf&yo3?D-vUS^*ZQFP5 z+_?t`_U%7(o;%RxOwaD-Mjbi-+%Dn!PBSDo<4j2?AeQ#FJHcY z|Nhgb&)>d%`~Lm=j~_pN|Ni~&-@pI={{uZZ3PwW!R|qJ6jdWmOU}Pu>@(Tv0mXQn? zg1@t?0>g>3z$3Dlfr0NJ2s7@OnEe(gC{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)W zs%L2E{@KYK7>re(E{-7{-fyqm3_4^W!j{l+X-B?C_Uj;rgIXHvc!NYkT%P{Dudb%< zJ^Narmh$7)KjqJ7tJt2Lli9c|Xu*5 z)J$8z=fSk=_)!O^{ZVhfKTu%ZcVB$9P;`aKfufcwskTKI6M14icxLK;@+r+&srtHb zHH*Q)>L)Y%`^$^%^iFxJAFFwDZ%?S)q|Y16ZEw~2oI9SH`ccHn^qrBFjKqhkhVAoA z@5t|cliYK9yU@C8ADLDg-kY$2N3@^8J4|Qi^TQ{2&YU@LhUd(m>;+$ht2DpedRzP6 Q4V2J5UHx3vIVCg!0JbYzga7~l diff --git a/lib/webserver/setup-ui/extras/package-lock.json b/lib/webserver/setup-ui/extras/package-lock.json deleted file mode 100644 index 0ede1b8e..00000000 --- a/lib/webserver/setup-ui/extras/package-lock.json +++ /dev/null @@ -1,202 +0,0 @@ -{ - "name": "extras", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "html-minifier": "^4.0.0" - } - }, - "node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-minifier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", - "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", - "dependencies": { - "camel-case": "^3.0.0", - "clean-css": "^4.2.1", - "commander": "^2.19.0", - "he": "^1.2.0", - "param-case": "^2.1.1", - "relateurl": "^0.2.7", - "uglify-js": "^3.5.1" - }, - "bin": { - "html-minifier": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==" - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==" - } - }, - "dependencies": { - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "requires": { - "source-map": "~0.6.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "html-minifier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", - "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", - "requires": { - "camel-case": "^3.0.0", - "clean-css": "^4.2.1", - "commander": "^2.19.0", - "he": "^1.2.0", - "param-case": "^2.1.1", - "relateurl": "^0.2.7", - "uglify-js": "^3.5.1" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==" - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "requires": { - "lower-case": "^1.1.1" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "requires": { - "no-case": "^2.2.0" - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==" - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==" - } - } -} diff --git a/lib/webserver/setup-ui/extras/package.json b/lib/webserver/setup-ui/extras/package.json deleted file mode 100644 index 4e90015d..00000000 --- a/lib/webserver/setup-ui/extras/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "html-minifier": "^4.0.0" - } -} diff --git a/lib/webserver/setup-ui/extras/reduce_index.sh b/lib/webserver/setup-ui/extras/reduce_index.sh deleted file mode 100644 index 7cb89406..00000000 --- a/lib/webserver/setup-ui/extras/reduce_index.sh +++ /dev/null @@ -1,59 +0,0 @@ -#/bin/sh - -# Processing script to optionally reduce filesystem use by miniying, gzipping and preparing index.htm for embedding in code. -# Please see readme.md for more information. - -# Requires xdd which is part of the VIM package -# Requires npm -# sudo apt install npm -# ln -s /usr/bin/nodejs /usr/bin/node -# Requires html-minifier -# sudo npm install html-minifier -g - -html-minifier \ - --case-sensitive \ - --collapse-boolean-attributes \ - --collapse-whitespace \ - --minify-css true \ - --minify-js true \ - --process-conditional-comments \ - --remove-attribute-quotes \ - --remove-comments \ - --remove-empty-attributes \ - --remove-optional-tags \ - --remove-redundant-attributes \ - --remove-script-type-attributes \ - --remove-style-link-type-attributes \ - -o edit.htm edit.htm - -if [ $? -ne 0 ] -then - echo "Error minifying index.htm" - exit -1 -fi - -if [ -e edit.htm.gz ] -then - rm edit.htm.gz -fi - -gzip edit.htm -if [ $? -ne 0 ] -then - echo "Error gzipping minified index.htm" - exit -1 -fi - -echo '// WARNING: Auto-generated file. Please do not modify by hand.' > edit_htm.h -echo '// This file is an embeddable version of the gzipped index.htm file.' >> edit_htm.h -echo '// To update it, please rerun the `reduce_index.sh` script located in the `extras` subfolder' >> edit_htm.h -echo '// then recompile the sketch after each change to the `index.html` file.' >> edit_htm.h -xxd -i edit.htm.gz >> edit_htm.h -if [ $? -ne 0 ] -then - echo "Error creating include file from index.htm.gz" - exit -1 -fi - -echo Reduce complete. - diff --git a/lib/webserver/setup-ui/readme.md b/lib/webserver/setup-ui/readme.md deleted file mode 100644 index 65c8935d..00000000 --- a/lib/webserver/setup-ui/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -If you want customize **/setup** page (headers, logo etc etc): -* edit the source files as your needs (setup.htm, app.js, style.css) -* put all togheter in the same all.htm file inside *dist* folder -* open a terminal in *dist* folder and run `npm i` to install all nodejs modules needed -* run `node finalize.js` -* overwrite the content of *setup_htm.h* in src folder diff --git a/lib/webserver/setup-ui/data/build/setup_htm.h b/lib/webserver/setup_htm.h similarity index 52% rename from lib/webserver/setup-ui/data/build/setup_htm.h rename to lib/webserver/setup_htm.h index 43ff83ba..efadb940 100644 --- a/lib/webserver/setup-ui/data/build/setup_htm.h +++ b/lib/webserver/setup_htm.h @@ -1,4 +1,4 @@ -#define SETUP_HTML_SIZE 8405 +#define SETUP_HTML_SIZE 8421 const char SETUP_HTML[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xed, 0x7d, 0xe9, 0x77, 0xdb, 0x46, 0x96, 0xef, 0xf7, 0x39, 0x67, 0xfe, 0x07, 0x84, 0x59, 0x2c, 0x8e, 0x01, 0x08, 0x0b, 0x09, 0x70, @@ -165,254 +165,255 @@ const char SETUP_HTML[] PROGMEM = { 0xf9, 0x55, 0xd0, 0x6e, 0xb7, 0x20, 0x45, 0x5c, 0xfc, 0x99, 0x6f, 0xff, 0x3a, 0xc0, 0x55, 0x51, 0x6c, 0xf3, 0xc9, 0xf9, 0xf9, 0x75, 0x72, 0x4b, 0x31, 0x7c, 0x2e, 0x32, 0xfb, 0x26, 0x2e, 0x56, 0xb7, 0xd7, 0x76, 0x9c, 0x9e, 0x47, 0xf7, 0x45, 0x16, 0x7f, 0x02, 0x23, 0xa1, 0x19, 0x17, 0xdf, - 0xa5, 0xf3, 0xe3, 0x04, 0x34, 0x99, 0x4e, 0x8e, 0xaf, 0x47, 0x38, 0xac, 0x6e, 0xd7, 0x16, 0x62, - 0xc9, 0x29, 0x0b, 0x90, 0x3d, 0x61, 0x04, 0x06, 0x9b, 0xf8, 0x4c, 0xe5, 0xba, 0x16, 0xbc, 0xcc, - 0x91, 0x6e, 0x52, 0x3b, 0xd0, 0x41, 0x19, 0xcf, 0x5a, 0x6c, 0x6e, 0xc9, 0x36, 0x92, 0x99, 0xca, - 0xb7, 0x2f, 0x79, 0xa9, 0x8b, 0x36, 0xa6, 0xff, 0x48, 0x02, 0xa7, 0x34, 0xc8, 0x83, 0x27, 0x19, - 0xf5, 0xa0, 0xaa, 0xe8, 0x70, 0x0c, 0x9b, 0xa3, 0x76, 0xd5, 0xa6, 0xb9, 0xdd, 0x52, 0xfa, 0x24, - 0x91, 0xd5, 0x8b, 0x94, 0x71, 0x6b, 0x65, 0xab, 0x7b, 0x9c, 0x74, 0x5b, 0x48, 0xfd, 0x6b, 0x41, - 0x5d, 0x79, 0x4d, 0xc3, 0xb2, 0xbc, 0x8b, 0x4b, 0x19, 0xda, 0xc9, 0x1b, 0x90, 0xb2, 0x62, 0x20, - 0xaf, 0xcb, 0xaa, 0xf4, 0x40, 0xbc, 0xba, 0xa5, 0x81, 0x20, 0x30, 0x74, 0x51, 0x53, 0x6f, 0xc3, - 0xcf, 0xc7, 0xd8, 0x51, 0xb0, 0x7b, 0xd5, 0xa0, 0x93, 0x38, 0x2f, 0xc0, 0xbe, 0xa2, 0xe6, 0x68, - 0x9b, 0x2c, 0x39, 0x06, 0xeb, 0xc5, 0x75, 0xf6, 0xeb, 0x9c, 0x43, 0x3d, 0xa7, 0xe9, 0x82, 0x47, - 0xe1, 0x45, 0x35, 0xa5, 0xc7, 0xc7, 0x75, 0xab, 0x9a, 0x6c, 0x9f, 0x52, 0xa8, 0xca, 0x9b, 0xe7, - 0x79, 0xbc, 0x50, 0x5d, 0x6b, 0xab, 0xfe, 0x17, 0xef, 0xde, 0xfd, 0xf0, 0xdd, 0x71, 0x1f, 0x5b, - 0xc2, 0xe1, 0x2e, 0x46, 0xb9, 0x46, 0x6c, 0xd4, 0x96, 0x50, 0x67, 0xbd, 0x57, 0x34, 0xd5, 0x93, - 0x1e, 0x1d, 0xf2, 0xfc, 0xc1, 0x20, 0x98, 0x7c, 0x8c, 0x82, 0xad, 0xa5, 0x47, 0x23, 0xf7, 0xca, - 0x83, 0x14, 0x87, 0x3c, 0xee, 0x56, 0xd0, 0x7f, 0x91, 0x5c, 0xbd, 0xbc, 0xdd, 0x41, 0xf2, 0x5b, - 0x55, 0xf5, 0x04, 0xb2, 0x6b, 0xa6, 0xdc, 0x98, 0xda, 0xb3, 0x91, 0x96, 0x25, 0x7a, 0xac, 0x13, - 0x90, 0x18, 0x5a, 0xe9, 0x50, 0xca, 0xae, 0x46, 0x35, 0x9d, 0xee, 0x95, 0x30, 0x09, 0xdc, 0x23, - 0xa0, 0xda, 0xc8, 0xc1, 0xfc, 0xd9, 0x77, 0x94, 0xaf, 0x96, 0xd0, 0x7e, 0x44, 0x3c, 0x88, 0x96, - 0xd3, 0x18, 0xe0, 0xaf, 0x76, 0x1a, 0xa7, 0xb8, 0x5f, 0x0e, 0xd4, 0xe9, 0x1e, 0x1f, 0xa1, 0x4c, - 0x3a, 0x4a, 0xcd, 0x9d, 0xdf, 0x8e, 0x9c, 0x4d, 0xfa, 0xbb, 0x53, 0xf4, 0x18, 0x84, 0xba, 0x31, - 0x94, 0x6a, 0x76, 0xc2, 0x20, 0x62, 0x43, 0xb7, 0x62, 0xa6, 0xe8, 0x97, 0xd3, 0x28, 0xd2, 0xda, - 0xd0, 0x3c, 0x5d, 0x6f, 0x13, 0x51, 0x08, 0x1d, 0x01, 0x4a, 0x45, 0x93, 0x71, 0x7f, 0x9d, 0x23, - 0x48, 0xd0, 0xbe, 0xce, 0xac, 0x57, 0x0d, 0xf0, 0x6b, 0xcd, 0xec, 0xc5, 0x79, 0x87, 0xbb, 0x79, - 0xc4, 0x97, 0xf5, 0xd4, 0x44, 0xca, 0xe8, 0xca, 0x5d, 0x94, 0x0d, 0xaa, 0x96, 0x72, 0x0e, 0x6c, - 0xe8, 0x6d, 0xd9, 0xa3, 0xc9, 0xce, 0xea, 0x98, 0x59, 0xcb, 0x84, 0x49, 0x27, 0x58, 0xd5, 0x84, - 0xfa, 0xe2, 0x5d, 0x81, 0xb9, 0xb9, 0x64, 0x2f, 0x66, 0x03, 0x74, 0x94, 0x27, 0x8e, 0x92, 0xfc, - 0x68, 0x72, 0xc3, 0xb0, 0xa4, 0xe0, 0x48, 0x06, 0x94, 0xf2, 0xe5, 0xb4, 0x14, 0x63, 0x34, 0x36, - 0xd5, 0x4a, 0xb4, 0xe5, 0x3c, 0x1f, 0x79, 0xaf, 0x5c, 0x19, 0x78, 0x82, 0x7f, 0xaa, 0xaf, 0x1c, - 0xfc, 0x33, 0xd9, 0xac, 0x4c, 0xf7, 0xe6, 0xd1, 0xa6, 0x91, 0xef, 0x81, 0xd3, 0x27, 0x33, 0xed, - 0x96, 0xc1, 0x28, 0x23, 0x21, 0x30, 0x8f, 0xe6, 0x0e, 0x4f, 0x35, 0x1a, 0x96, 0xc0, 0xc5, 0x3b, - 0x02, 0xc9, 0xdc, 0xde, 0x88, 0x02, 0xaa, 0xf6, 0xf1, 0x38, 0xab, 0x4f, 0xa5, 0x6f, 0x2a, 0x02, - 0xfe, 0x06, 0x34, 0x2a, 0x48, 0xbf, 0x31, 0x99, 0xb5, 0xd4, 0xa4, 0x4c, 0xd5, 0x29, 0x7e, 0x59, - 0x14, 0xce, 0x54, 0xb0, 0x7c, 0x32, 0xd9, 0x87, 0x19, 0x55, 0xeb, 0x5d, 0x65, 0x39, 0x6c, 0x4e, - 0x95, 0xf2, 0x69, 0xeb, 0x62, 0x37, 0xda, 0x06, 0xd9, 0x61, 0x5d, 0x9d, 0x56, 0x78, 0x60, 0x50, - 0xdd, 0xaa, 0x27, 0xa5, 0x82, 0x59, 0x3a, 0x2d, 0xcf, 0x3f, 0x22, 0x90, 0x13, 0xc2, 0xd0, 0x00, - 0x7e, 0x0b, 0x61, 0x48, 0x41, 0xfc, 0x49, 0x41, 0x7c, 0xf5, 0xee, 0x6d, 0x27, 0xc7, 0x3b, 0xb8, - 0x2d, 0x2d, 0x28, 0xba, 0xa3, 0x90, 0x93, 0x45, 0xeb, 0xfc, 0x9f, 0x27, 0x87, 0x80, 0xfc, 0x86, - 0xb4, 0xbc, 0x23, 0x70, 0xd0, 0xd7, 0x65, 0x7c, 0x73, 0x2b, 0xcf, 0xd5, 0x3c, 0x81, 0xa4, 0x3a, - 0xc8, 0x17, 0xe7, 0x34, 0xeb, 0xd7, 0x2f, 0x35, 0x47, 0x2c, 0x0f, 0xf1, 0x19, 0x65, 0xc0, 0x95, - 0xef, 0x17, 0x57, 0x29, 0xa7, 0xda, 0xb6, 0x6d, 0x37, 0xa0, 0xa8, 0xc3, 0x2d, 0xbc, 0x8a, 0xc0, - 0x47, 0x9f, 0xd6, 0x22, 0xcf, 0xa3, 0x9b, 0x7a, 0x7e, 0xfb, 0x42, 0x1d, 0x76, 0x21, 0xba, 0xd4, - 0x53, 0x4b, 0x5f, 0xe5, 0xc8, 0xea, 0xf0, 0xd4, 0xa1, 0x08, 0xd2, 0xcd, 0x9c, 0x66, 0xfa, 0x33, - 0x3e, 0x2c, 0xf6, 0x86, 0xda, 0xbc, 0x91, 0x83, 0x9c, 0xf5, 0x4f, 0xcb, 0xa0, 0x71, 0xca, 0xec, - 0xa8, 0x8d, 0x4a, 0x19, 0x71, 0x1b, 0xd9, 0xde, 0x90, 0x67, 0x7a, 0xdd, 0x81, 0x21, 0x97, 0xb1, - 0xe9, 0xa9, 0x21, 0x27, 0xbc, 0xbb, 0x83, 0x9e, 0x94, 0x26, 0x2d, 0x22, 0x1d, 0x9d, 0x2d, 0x75, - 0x06, 0xbd, 0x43, 0x2d, 0x3b, 0xc4, 0xf8, 0xe8, 0x52, 0x0a, 0xa6, 0x3e, 0xc4, 0x6a, 0x49, 0xbf, - 0x6a, 0xd6, 0x35, 0xd9, 0x39, 0x1d, 0x6d, 0x5b, 0xe7, 0xd4, 0xba, 0x06, 0xda, 0xd6, 0xc7, 0xe1, - 0xb9, 0xcc, 0x8b, 0xf3, 0xed, 0xaf, 0x1b, 0x45, 0x39, 0x9d, 0xa3, 0x8e, 0x3b, 0xfd, 0xa8, 0xf8, - 0x5d, 0x19, 0x95, 0x52, 0xbb, 0xe3, 0x12, 0x2f, 0xb2, 0x5b, 0xd1, 0xbf, 0x90, 0x36, 0xf0, 0xd3, - 0xff, 0x55, 0x3a, 0x7f, 0x32, 0x3a, 0xd4, 0xe4, 0x5a, 0x33, 0xde, 0x13, 0x43, 0x2c, 0x11, 0xf3, - 0xcb, 0x31, 0x2e, 0xa9, 0xfa, 0xe8, 0x30, 0xa7, 0xbc, 0x31, 0x9e, 0xa5, 0x6d, 0x94, 0xa7, 0xbd, - 0xe7, 0x59, 0xbc, 0x2d, 0x2e, 0xa0, 0x29, 0x57, 0xe9, 0x4d, 0x3a, 0x7b, 0xc6, 0x9a, 0x27, 0x55, - 0x2d, 0xa0, 0xb3, 0x1e, 0x4a, 0xd9, 0xf8, 0xb9, 0xe9, 0x16, 0x46, 0xf8, 0x0b, 0xb7, 0xb0, 0x8d, - 0x8a, 0x95, 0x81, 0xc9, 0xcf, 0x1b, 0xd7, 0xb3, 0xc7, 0x5e, 0x60, 0xb8, 0x63, 0xdb, 0xf7, 0x06, - 0x51, 0x68, 0x07, 0x06, 0xfd, 0xe3, 0x6d, 0x0c, 0x0b, 0x55, 0x23, 0xdf, 0x0a, 0xec, 0x70, 0x38, - 0x40, 0xe9, 0x40, 0x5d, 0x64, 0x9d, 0x6f, 0x8f, 0xbc, 0x91, 0xe5, 0xda, 0xc3, 0xe1, 0xc0, 0x0e, - 0xc6, 0x21, 0xfd, 0x93, 0x5b, 0x1f, 0x96, 0x1d, 0x38, 0x81, 0x65, 0x87, 0xbe, 0x6b, 0x07, 0xe1, - 0x80, 0xfe, 0xc9, 0x72, 0xc3, 0x0e, 0x07, 0x3e, 0x2a, 0xdd, 0xd0, 0x18, 0xd9, 0x63, 0x75, 0x91, - 0x35, 0x23, 0x63, 0x6c, 0x8f, 0x9c, 0x21, 0xc0, 0x03, 0xa6, 0xba, 0x2a, 0x58, 0xde, 0x78, 0x64, - 0x60, 0x90, 0x81, 0x97, 0xb8, 0x40, 0x66, 0x6c, 0x0f, 0x83, 0xc8, 0x75, 0x6d, 0xc7, 0x1f, 0x1b, - 0xea, 0xa6, 0x36, 0x5c, 0xec, 0xd0, 0x1d, 0x00, 0xf8, 0xd0, 0x35, 0x40, 0x90, 0x3b, 0x1c, 0xeb, - 0x9b, 0xac, 0xb6, 0x3d, 0x37, 0x04, 0x35, 0xfe, 0xc0, 0x7f, 0x89, 0xf2, 0x61, 0x68, 0xc8, 0xab, - 0xac, 0x0c, 0x51, 0xeb, 0x19, 0x81, 0xed, 0x86, 0x6e, 0x34, 0xb4, 0x87, 0xbe, 0xc1, 0x17, 0xc5, - 0x01, 0x5c, 0x07, 0xb6, 0x0f, 0xfa, 0xe5, 0x55, 0xf3, 0xc5, 0x05, 0xc7, 0x6c, 0xdf, 0x0f, 0x51, - 0xec, 0x85, 0x03, 0x75, 0xd5, 0xa8, 0x8c, 0x9d, 0x31, 0xc0, 0x8d, 0x86, 0x01, 0x91, 0x35, 0xd6, - 0x57, 0x5d, 0xeb, 0x80, 0x29, 0xee, 0x78, 0x88, 0x3e, 0x8e, 0xeb, 0xaa, 0xab, 0x64, 0x83, 0xcf, - 0x10, 0x7d, 0x7b, 0x8c, 0x81, 0x70, 0x0d, 0x86, 0xea, 0xaa, 0xd9, 0x0a, 0x8f, 0x8e, 0x81, 0xc1, - 0x08, 0x3f, 0x74, 0xed, 0xd1, 0x28, 0x72, 0x1d, 0xdb, 0x1d, 0x79, 0x86, 0xba, 0x49, 0xf8, 0x9e, - 0xed, 0x0c, 0x43, 0x10, 0xea, 0x81, 0xac, 0xa1, 0xba, 0x28, 0x1e, 0x40, 0x8a, 0xc0, 0x3c, 0xf0, - 0x46, 0x6b, 0x42, 0x7f, 0x00, 0x09, 0xbd, 0x74, 0x7d, 0xa0, 0xe3, 0x1b, 0xea, 0xa6, 0xc4, 0xe4, - 0x38, 0x2e, 0xc1, 0x84, 0xe8, 0x89, 0x4d, 0x63, 0x1a, 0x41, 0xde, 0x34, 0x96, 0x54, 0x81, 0xde, - 0x61, 0x42, 0x12, 0x25, 0xc1, 0x47, 0x68, 0xe0, 0x04, 0xcc, 0x55, 0xba, 0x39, 0x9a, 0xd6, 0xd0, - 0x76, 0x07, 0xae, 0xd1, 0x55, 0xa9, 0xaa, 0x9c, 0x44, 0xeb, 0x0e, 0x81, 0x18, 0x73, 0xa3, 0x52, - 0x8f, 0xa0, 0x91, 0x7e, 0x80, 0xe1, 0x42, 0x2f, 0x78, 0x83, 0x68, 0x46, 0x28, 0x8d, 0x81, 0x32, - 0xdf, 0xd4, 0x9b, 0x86, 0x86, 0x5e, 0x03, 0xc8, 0x3a, 0x81, 0x3e, 0xba, 0x40, 0x09, 0x2c, 0x80, - 0xe6, 0x0c, 0x3d, 0x20, 0xe9, 0x45, 0x2e, 0x14, 0x0d, 0xf2, 0x55, 0x37, 0x49, 0x03, 0x74, 0x67, - 0x38, 0x1a, 0xf1, 0x2d, 0x0c, 0x12, 0xd2, 0x55, 0xb4, 0x0f, 0xfc, 0xb9, 0x63, 0xd9, 0x7e, 0x10, - 0x00, 0xcf, 0x31, 0x29, 0xb0, 0xc7, 0x0f, 0x0c, 0x72, 0x8d, 0x9b, 0x17, 0x8c, 0xa1, 0x1a, 0x6e, - 0x30, 0x7c, 0x09, 0xec, 0xa1, 0x21, 0xf2, 0xaa, 0x75, 0x68, 0xe4, 0x92, 0xa2, 0x7a, 0x21, 0xa9, - 0xa7, 0xeb, 0xb2, 0x7a, 0xd2, 0x4d, 0x2b, 0xcc, 0x80, 0x94, 0xce, 0x0e, 0xc3, 0x3b, 0x58, 0x85, - 0x3f, 0x24, 0xc6, 0x8f, 0xa9, 0x91, 0xbc, 0x29, 0xa4, 0xc6, 0x18, 0x62, 0x44, 0x88, 0x0e, 0xc3, - 0x15, 0x35, 0x1b, 0x10, 0xac, 0xd0, 0xf5, 0x0d, 0x75, 0x2b, 0x55, 0x3d, 0x74, 0x09, 0xe2, 0x20, - 0x78, 0x13, 0xc2, 0x76, 0x09, 0x8f, 0xd1, 0x08, 0x6d, 0xc1, 0x46, 0x00, 0xe1, 0x2b, 0x83, 0xb3, - 0xe8, 0xd9, 0xaa, 0x17, 0xeb, 0x4a, 0xae, 0xc6, 0xb3, 0x2c, 0xa0, 0x49, 0x99, 0x0c, 0x3a, 0xcf, - 0xa6, 0x70, 0xe2, 0x79, 0x61, 0xe0, 0xf9, 0x8d, 0xd8, 0xdc, 0xc2, 0xad, 0x94, 0x6e, 0xc2, 0x37, - 0x83, 0xd7, 0x9e, 0xfb, 0x7e, 0xf4, 0xda, 0x7f, 0x1f, 0xe0, 0xc5, 0x75, 0xe9, 0xcd, 0xf5, 0xf1, - 0xea, 0xba, 0xf4, 0xce, 0xb5, 0x2e, 0x55, 0xbb, 0xc1, 0x5f, 0x7b, 0xe7, 0x17, 0xcf, 0x4c, 0xf6, - 0x4d, 0x70, 0x8a, 0xd2, 0x37, 0x29, 0x87, 0xd4, 0x73, 0x83, 0x6d, 0xd1, 0x6b, 0xba, 0xa4, 0x21, - 0xc4, 0x82, 0x7f, 0x35, 0xa7, 0xb4, 0x26, 0xc1, 0xa3, 0x68, 0x65, 0x79, 0xa3, 0xd1, 0xdc, 0xf2, - 0x02, 0xb0, 0xcf, 0x77, 0x3d, 0x58, 0x82, 0x35, 0x18, 0x59, 0x1e, 0xa4, 0xe6, 0xc1, 0x94, 0x47, - 0xf4, 0x32, 0x18, 0xdd, 0x59, 0x9e, 0x37, 0x80, 0xe4, 0xa8, 0x55, 0x18, 0x0c, 0x03, 0xcf, 0xa0, - 0x06, 0x83, 0x60, 0x14, 0x0e, 0x51, 0x6b, 0x70, 0x9b, 0x15, 0xc1, 0xa9, 0x81, 0x41, 0xa9, 0x51, - 0x82, 0x31, 0xb8, 0xd5, 0x1d, 0x43, 0x31, 0x4a, 0x28, 0x56, 0x09, 0x45, 0x82, 0xc0, 0xf5, 0xf3, - 0x9a, 0xf0, 0x91, 0x38, 0x8d, 0x20, 0x70, 0x46, 0xc8, 0x25, 0x87, 0xe9, 0x06, 0xe1, 0x98, 0x78, - 0x0d, 0xaf, 0x10, 0x28, 0x40, 0x68, 0xe0, 0x7b, 0x8e, 0xef, 0x52, 0x2d, 0x01, 0xe1, 0x3a, 0xfc, - 0x65, 0x54, 0x74, 0x6f, 0xbc, 0x5b, 0xba, 0x37, 0x3d, 0xa3, 0xb7, 0xa2, 0x46, 0x77, 0xb7, 0x64, - 0x77, 0x8b, 0x2b, 0xf1, 0xf7, 0xf3, 0x1a, 0x2c, 0x03, 0x7f, 0x6b, 0xbc, 0x72, 0xe0, 0x17, 0xd0, - 0xa7, 0xec, 0xc2, 0x48, 0x59, 0x35, 0xa4, 0x18, 0xec, 0xc8, 0x01, 0xd4, 0x21, 0x39, 0xfb, 0x71, - 0x00, 0x22, 0xc8, 0x4a, 0x42, 0x34, 0xf6, 0xac, 0x71, 0x20, 0xff, 0xe6, 0xf8, 0x67, 0xd4, 0x8b, - 0x8d, 0x71, 0x70, 0x47, 0xbd, 0x8c, 0x3a, 0x2e, 0x35, 0x54, 0x71, 0xcd, 0x8f, 0x8e, 0x14, 0x3a, - 0xf6, 0x70, 0xec, 0x83, 0x6e, 0x78, 0xa3, 0x81, 0x13, 0x78, 0xa0, 0x00, 0x4e, 0xdd, 0xa5, 0x90, - 0xe1, 0x8d, 0x72, 0x7a, 0xd6, 0x15, 0x86, 0xaa, 0x78, 0x6c, 0xac, 0x92, 0x72, 0xa9, 0xaa, 0xa4, - 0x5f, 0x7f, 0xde, 0x24, 0xff, 0x5f, 0xc3, 0x7e, 0x7f, 0x0d, 0x1b, 0x39, 0x4f, 0x56, 0xb0, 0x5f, - 0x2f, 0xf6, 0x5f, 0xab, 0x5f, 0xbf, 0x83, 0x16, 0x77, 0x68, 0x16, 0x2d, 0x27, 0xd4, 0xdd, 0x1f, - 0x05, 0x10, 0xef, 0x72, 0x2c, 0x43, 0x14, 0x40, 0x71, 0x54, 0x43, 0x34, 0x0b, 0x90, 0x2b, 0xc1, - 0x89, 0x8f, 0xae, 0x06, 0x36, 0x87, 0x93, 0xc1, 0x25, 0x02, 0xbf, 0xcb, 0x11, 0x1f, 0x17, 0xdf, - 0xa0, 0x3c, 0xc4, 0x18, 0xbf, 0xa3, 0x70, 0x37, 0x96, 0xa5, 0xe4, 0xe5, 0xb9, 0xe5, 0x15, 0x1c, - 0x3d, 0x92, 0x06, 0x80, 0xc5, 0x43, 0x10, 0x18, 0x32, 0x46, 0x0d, 0x47, 0xfa, 0x81, 0x6b, 0xc0, - 0x2c, 0x9f, 0x0b, 0xa0, 0x34, 0x1c, 0x87, 0x29, 0x55, 0xe3, 0xfc, 0x04, 0xcf, 0x21, 0x1a, 0x0c, - 0xa0, 0x71, 0xba, 0xdc, 0xe7, 0xab, 0x27, 0xff, 0xbe, 0xf1, 0x80, 0xc6, 0x95, 0xe7, 0x01, 0x2f, - 0x20, 0x79, 0x89, 0x61, 0xc3, 0x31, 0x25, 0x31, 0x03, 0x82, 0x85, 0x5c, 0x8b, 0xc1, 0xfa, 0xef, - 0x90, 0xb9, 0xb8, 0xaa, 0xd8, 0xa6, 0x24, 0x28, 0xb8, 0x02, 0xd2, 0x97, 0x18, 0x81, 0xb4, 0x8a, - 0x28, 0x85, 0xb6, 0x33, 0xd0, 0xe0, 0x1d, 0x23, 0xc5, 0xa5, 0x04, 0x9a, 0x59, 0x32, 0xbc, 0x44, - 0x1c, 0x46, 0x86, 0xe2, 0x0e, 0x41, 0xdc, 0x80, 0x30, 0x03, 0x36, 0x23, 0x9b, 0xc7, 0xf0, 0xae, - 0xb8, 0x25, 0xae, 0x04, 0xdd, 0x83, 0x62, 0x0c, 0x2e, 0x29, 0x29, 0xf3, 0x89, 0x05, 0xcc, 0x17, - 0x62, 0x85, 0xa7, 0xc9, 0xbd, 0x74, 0x39, 0x92, 0x51, 0xa0, 0x47, 0x87, 0x80, 0xb1, 0x04, 0x2f, - 0x7c, 0x02, 0xea, 0x8c, 0xa8, 0x67, 0xc0, 0xa4, 0x3b, 0x4c, 0xba, 0x4f, 0xe5, 0xdc, 0x75, 0xf8, - 0x86, 0x02, 0xef, 0x80, 0x00, 0x0c, 0x89, 0x44, 0x7a, 0xe4, 0x49, 0x15, 0x30, 0x18, 0xf3, 0x03, - 0x80, 0xbf, 0x93, 0x75, 0xe0, 0x06, 0xea, 0x46, 0x7c, 0x27, 0x8e, 0x04, 0xf2, 0x91, 0x0c, 0x95, - 0x71, 0x85, 0x61, 0xd2, 0x35, 0x74, 0x81, 0xee, 0x6b, 0xcf, 0xa1, 0x26, 0x43, 0x46, 0x3d, 0x70, - 0x09, 0xcc, 0x88, 0x29, 0xa7, 0xfe, 0xee, 0x25, 0xc0, 0x07, 0xf2, 0x95, 0x78, 0x85, 0x86, 0x94, - 0x4e, 0xf0, 0x23, 0x0f, 0xc7, 0xb5, 0xa4, 0x5c, 0x28, 0x0d, 0x58, 0xc0, 0x63, 0x7e, 0xa5, 0x2c, - 0x9b, 0x51, 0x1b, 0xd1, 0x73, 0x18, 0xd2, 0x73, 0xe8, 0x5f, 0xb9, 0x32, 0xec, 0xbf, 0xf6, 0xbc, - 0xf7, 0x84, 0xff, 0x15, 0x86, 0x1c, 0x31, 0xe5, 0x41, 0x78, 0x89, 0x67, 0x64, 0x88, 0x28, 0x1e, - 0xf3, 0x38, 0xf2, 0x99, 0xc9, 0xa0, 0xfb, 0x5f, 0x29, 0x7a, 0xb3, 0xca, 0xaa, 0xa5, 0xa1, 0x96, - 0xd6, 0x06, 0x97, 0x4a, 0x84, 0xa5, 0x48, 0x21, 0xdf, 0x2b, 0x25, 0xeb, 0xcb, 0x4a, 0xfa, 0x21, - 0x81, 0x57, 0x3a, 0x51, 0xd3, 0x15, 0xad, 0x3f, 0x57, 0x24, 0xf2, 0xcb, 0x4a, 0x03, 0x80, 0x1a, - 0xdc, 0x9a, 0x54, 0x8c, 0x37, 0xa0, 0x61, 0x34, 0x20, 0xf5, 0x1b, 0xb8, 0xa4, 0xb1, 0x84, 0x19, - 0x54, 0x31, 0xe4, 0x04, 0x69, 0x48, 0xcf, 0x2e, 0x3f, 0x53, 0xaa, 0x82, 0xe7, 0xab, 0xd2, 0x02, - 0x2e, 0xeb, 0x66, 0x81, 0x7c, 0x54, 0x5b, 0x4b, 0x65, 0x42, 0xda, 0xaa, 0xae, 0xb4, 0x9d, 0x5d, - 0x56, 0xa6, 0xa7, 0x8d, 0x51, 0x9a, 0x26, 0x2a, 0x43, 0x69, 0x3a, 0x43, 0x9a, 0xa3, 0xb8, 0x2c, - 0xe9, 0x0a, 0xaf, 0xa7, 0x6b, 0x2b, 0x5c, 0xc7, 0x80, 0xf8, 0x1c, 0x80, 0x16, 0x56, 0x55, 0xca, - 0x60, 0xf9, 0xc1, 0x53, 0x0f, 0x5c, 0x1e, 0xb2, 0x3a, 0xfa, 0x3c, 0x56, 0xc0, 0x46, 0x4a, 0x59, - 0x3d, 0xc3, 0xf4, 0x09, 0x19, 0x1a, 0x85, 0x67, 0x09, 0x1e, 0x4b, 0x59, 0xeb, 0xaa, 0x47, 0x00, - 0xae, 0x68, 0x5f, 0x34, 0xa0, 0x6c, 0x09, 0x57, 0xd6, 0xb4, 0xf7, 0x9e, 0x77, 0xc5, 0x55, 0x95, - 0x38, 0x69, 0x51, 0xa6, 0x21, 0xcb, 0xa1, 0x39, 0x7e, 0x3d, 0x7c, 0x3f, 0x7c, 0x4d, 0x1a, 0xef, - 0x99, 0xee, 0xf8, 0xa5, 0x6f, 0x72, 0x4a, 0x68, 0x82, 0x57, 0xc8, 0xbf, 0x6a, 0xaf, 0x54, 0xed, - 0xd7, 0xdf, 0x87, 0x87, 0xf5, 0xb0, 0xdf, 0xd0, 0xf4, 0x5f, 0x0f, 0x2f, 0xc1, 0xd4, 0x31, 0x6a, - 0x50, 0x0b, 0xa3, 0xf4, 0xcd, 0xe1, 0x7b, 0x40, 0xf6, 0x4c, 0x4e, 0x94, 0x4d, 0x44, 0x4e, 0xd3, - 0x73, 0x5f, 0x37, 0x4a, 0x3c, 0x17, 0x9d, 0xdf, 0x87, 0x57, 0xd4, 0xbd, 0xc2, 0x56, 0x2d, 0x87, - 0x35, 0x95, 0xcf, 0x1c, 0x90, 0x7f, 0x72, 0x4d, 0x66, 0x11, 0x6e, 0x24, 0x4c, 0xf0, 0xcd, 0x0c, - 0x6c, 0x9f, 0xb4, 0x3a, 0x34, 0x49, 0x0a, 0xfc, 0x20, 0x35, 0x9a, 0xea, 0xe8, 0x42, 0x96, 0x3c, - 0x32, 0xc9, 0xf8, 0x88, 0xc3, 0xbe, 0x89, 0x26, 0x3c, 0xcb, 0x19, 0x53, 0x19, 0x94, 0x17, 0x0a, - 0x41, 0xed, 0x48, 0x10, 0x00, 0xeb, 0xb2, 0x4a, 0x0c, 0xa8, 0x36, 0x94, 0x42, 0x07, 0x79, 0xb8, - 0xb0, 0xb6, 0x9a, 0x94, 0x61, 0x1b, 0xf2, 0xc9, 0xa1, 0x76, 0x54, 0x1b, 0xda, 0x21, 0x0d, 0xe1, - 0x9a, 0x4a, 0xab, 0x86, 0x26, 0xc9, 0xc9, 0x84, 0x44, 0xa0, 0x1e, 0x57, 0xa1, 0x09, 0xb3, 0x83, - 0x36, 0x98, 0x78, 0x79, 0x3f, 0x78, 0x03, 0x64, 0x25, 0x52, 0x3e, 0xe1, 0x49, 0x53, 0x32, 0xca, - 0x7e, 0x69, 0x22, 0x00, 0x38, 0x63, 0x52, 0x4c, 0x22, 0x83, 0x3c, 0x26, 0x8a, 0x6d, 0xb2, 0xb3, - 0x31, 0x91, 0x43, 0x16, 0x35, 0x92, 0x78, 0x8c, 0xa8, 0x07, 0xcc, 0x9c, 0x66, 0xbc, 0x04, 0x8a, - 0x74, 0x9b, 0x09, 0x1d, 0x5c, 0x31, 0x45, 0x83, 0x4b, 0x22, 0x96, 0xec, 0x8a, 0x68, 0x19, 0x18, - 0x7a, 0xc4, 0x8a, 0xbb, 0xaf, 0x1e, 0x44, 0xdb, 0xac, 0xed, 0xe1, 0x1c, 0x9a, 0x45, 0xb3, 0x4a, - 0xb8, 0x2f, 0xf2, 0x9a, 0x08, 0xb9, 0x34, 0xc9, 0x1b, 0x62, 0x26, 0xe3, 0xf2, 0xc4, 0x99, 0x3c, - 0xfa, 0x20, 0x48, 0xa0, 0xcf, 0x34, 0x89, 0x72, 0x82, 0x39, 0xe6, 0x8d, 0x34, 0x1d, 0x80, 0x9e, - 0x61, 0xf2, 0x30, 0xb6, 0x58, 0x31, 0xc1, 0xc0, 0x11, 0x7d, 0x71, 0x0b, 0x81, 0xd0, 0xe4, 0x85, - 0x90, 0x40, 0x6f, 0x4c, 0x6b, 0x49, 0x5f, 0x11, 0xf2, 0xb9, 0x90, 0xe7, 0x2f, 0xd0, 0x7f, 0xcc, - 0xf9, 0x03, 0xb4, 0x0d, 0x13, 0x8f, 0x2c, 0x9a, 0x2e, 0x73, 0x78, 0x4c, 0x8c, 0x07, 0xe6, 0x07, - 0x7a, 0x44, 0x9a, 0x79, 0x0d, 0x3e, 0xbf, 0xf1, 0xc8, 0x8b, 0x02, 0x7a, 0x30, 0xc7, 0x94, 0x6a, - 0x4c, 0x23, 0xdb, 0x34, 0x67, 0xb7, 0x1d, 0x8f, 0xa7, 0x30, 0x03, 0x97, 0xe6, 0xf3, 0x34, 0x25, - 0x1a, 0x87, 0x97, 0x8c, 0x62, 0xa8, 0xa6, 0x95, 0x64, 0xd8, 0x14, 0xde, 0x78, 0x72, 0x66, 0xd0, - 0x14, 0x8e, 0x2c, 0x09, 0xbe, 0x00, 0x8d, 0x55, 0xd4, 0x98, 0xbb, 0x72, 0x56, 0x4b, 0x73, 0x45, - 0x80, 0x25, 0x4f, 0x05, 0x82, 0x47, 0x5e, 0x42, 0x21, 0x91, 0xba, 0x78, 0x73, 0x39, 0x26, 0x8f, - 0x27, 0xef, 0x34, 0xd9, 0x34, 0x14, 0x1a, 0x92, 0x0f, 0x84, 0x89, 0x45, 0x15, 0x88, 0xdd, 0xb0, - 0xe8, 0x12, 0x57, 0x4b, 0x55, 0xfb, 0xea, 0x01, 0x71, 0xd7, 0xf9, 0xfc, 0x46, 0xc6, 0xe0, 0xe1, - 0xdc, 0x92, 0x5c, 0xb7, 0x86, 0x16, 0x71, 0x1d, 0x37, 0xca, 0xd0, 0x80, 0x35, 0xf1, 0x11, 0x68, - 0x49, 0xc6, 0xba, 0x83, 0xc4, 0xe5, 0x55, 0x06, 0x5c, 0x00, 0xd3, 0x61, 0x2e, 0x83, 0x48, 0x4c, - 0xdc, 0xf9, 0xc6, 0x4b, 0x0f, 0x2e, 0x7b, 0x10, 0x72, 0xb2, 0x3e, 0xff, 0xb1, 0x3d, 0xc6, 0x70, - 0xc4, 0xed, 0x69, 0x02, 0xeb, 0xc0, 0xc8, 0x80, 0x1a, 0x59, 0xcf, 0x9c, 0x96, 0x36, 0x10, 0x3a, - 0xe8, 0x8b, 0x63, 0x28, 0x39, 0x0f, 0x61, 0x0f, 0x3f, 0xaf, 0x99, 0x03, 0xa8, 0xf0, 0xd1, 0xc0, - 0x1d, 0x12, 0xb2, 0x24, 0xb1, 0xa1, 0xa5, 0x04, 0x1c, 0xf0, 0x84, 0x7f, 0x90, 0x78, 0x72, 0xed, - 0x20, 0x18, 0x7c, 0x2e, 0x55, 0xea, 0xc7, 0xb4, 0xa5, 0x54, 0xb0, 0xee, 0x95, 0x37, 0xb8, 0xf3, - 0x06, 0xaf, 0x9d, 0xf7, 0xce, 0x67, 0xb5, 0x20, 0xd9, 0xa3, 0x15, 0xc9, 0x7a, 0x2e, 0x48, 0x7c, - 0xa0, 0x58, 0x4b, 0x0b, 0x1f, 0x4a, 0x3a, 0x21, 0x47, 0x47, 0x48, 0x66, 0x4e, 0x8b, 0x02, 0x24, - 0x8c, 0xb1, 0x41, 0xe2, 0x84, 0x29, 0x52, 0x6a, 0x3a, 0xcc, 0xa1, 0x39, 0x21, 0x54, 0x87, 0x14, - 0x8b, 0x92, 0xaf, 0x21, 0x69, 0x55, 0xe8, 0x5b, 0xd4, 0xd0, 0xa2, 0xec, 0x0e, 0x78, 0x73, 0xb9, - 0x64, 0x72, 0xd8, 0xc1, 0xe2, 0x5c, 0x3e, 0x18, 0xc4, 0xed, 0x4a, 0xdd, 0x2d, 0xf9, 0x40, 0x65, - 0xc8, 0xe0, 0xac, 0x11, 0xc1, 0x0d, 0xa8, 0xa3, 0xcf, 0x6c, 0xc5, 0xcd, 0xcf, 0x6b, 0xfc, 0xf5, - 0x2d, 0xf9, 0x62, 0xc9, 0x07, 0x8b, 0x1e, 0xfc, 0xcf, 0x7a, 0xaa, 0x7a, 0x59, 0x2e, 0xdd, 0x69, - 0xa6, 0xf0, 0xb9, 0xc9, 0xec, 0x36, 0x11, 0xb3, 0x9e, 0xb8, 0x13, 0x9b, 0x74, 0xb1, 0xa0, 0x63, - 0x66, 0xf1, 0xb6, 0x5d, 0xc6, 0x5c, 0x81, 0x73, 0x70, 0x42, 0x9a, 0x54, 0xd3, 0xcd, 0x25, 0xb7, - 0xe7, 0x8c, 0x43, 0x16, 0xaf, 0x1b, 0x0c, 0x39, 0x52, 0xf3, 0x3b, 0x5c, 0xca, 0xc8, 0x1f, 0x50, - 0x38, 0x54, 0x1d, 0xe0, 0xd9, 0xc6, 0xde, 0x68, 0xcc, 0x21, 0x03, 0x4d, 0x03, 0xc3, 0x72, 0xb8, - 0xa5, 0xef, 0xca, 0x30, 0x87, 0xd6, 0xad, 0x22, 0xb4, 0x1f, 0x97, 0xdd, 0xae, 0x42, 0x8a, 0xeb, - 0xa3, 0x61, 0x48, 0x21, 0x9d, 0x87, 0xae, 0x41, 0x54, 0x63, 0xd7, 0xba, 0x97, 0xc3, 0x37, 0xca, - 0x64, 0xfb, 0xaa, 0xe3, 0x23, 0x1d, 0x34, 0xdc, 0xb2, 0xa3, 0x1a, 0xf9, 0x4a, 0x61, 0x62, 0x84, - 0x57, 0x55, 0x95, 0xc4, 0xf7, 0xf2, 0x11, 0xaa, 0x14, 0xed, 0x55, 0x37, 0xc9, 0x9d, 0xcb, 0x8a, - 0x5d, 0x47, 0xf8, 0xa9, 0x89, 0x56, 0x1d, 0xae, 0xc8, 0xc7, 0x0e, 0xdc, 0x81, 0xcc, 0x3a, 0x99, - 0x53, 0x1a, 0x94, 0x1e, 0xb6, 0xec, 0xa9, 0xc6, 0xac, 0xbd, 0x4b, 0x09, 0xea, 0xf6, 0xc7, 0xda, - 0x69, 0x38, 0xba, 0xbd, 0x1c, 0xe7, 0x4a, 0x8d, 0x0b, 0xe2, 0x5b, 0xba, 0xf0, 0x57, 0x6d, 0x4a, - 0xd7, 0x49, 0x44, 0x3b, 0xb6, 0xd0, 0xb7, 0xe9, 0x5d, 0x94, 0xd1, 0x79, 0xa4, 0x38, 0xdd, 0xe4, - 0xb3, 0xdd, 0xde, 0xfc, 0x6a, 0xb6, 0xbc, 0xdd, 0xf0, 0x59, 0xdf, 0x33, 0xd1, 0xdf, 0x65, 0xa2, - 0xb8, 0xcd, 0x36, 0xc6, 0x22, 0x9d, 0xdf, 0xae, 0xc5, 0xa6, 0xb0, 0x6f, 0x44, 0xf1, 0x2a, 0x11, - 0xf4, 0xf8, 0xc7, 0x87, 0x1f, 0x16, 0x68, 0xb1, 0x9f, 0xea, 0xe6, 0x06, 0x1d, 0x67, 0x78, 0x1d, - 0x2f, 0x84, 0x3e, 0x32, 0x72, 0xd6, 0xdf, 0x11, 0x6c, 0x31, 0xfb, 0xea, 0xac, 0xda, 0x73, 0xef, - 0x4f, 0xe9, 0xe8, 0x59, 0x63, 0x59, 0xba, 0xa7, 0xe2, 0xf5, 0x17, 0x3d, 0xb3, 0x47, 0x47, 0x85, - 0x5e, 0xbd, 0x7b, 0x6b, 0xa8, 0x3d, 0x32, 0xb1, 0xb0, 0x8d, 0xb7, 0x09, 0x7d, 0x99, 0x68, 0xdc, - 0x47, 0x71, 0x61, 0x44, 0x46, 0x12, 0x17, 0x45, 0x22, 0xf8, 0x34, 0x6b, 0xb1, 0x12, 0x1b, 0x3a, - 0xce, 0x46, 0x27, 0x24, 0x8b, 0x55, 0x9c, 0x1b, 0x5b, 0x40, 0xb3, 0x09, 0x42, 0xaf, 0x6f, 0x56, - 0x23, 0xce, 0x66, 0x33, 0x61, 0xd3, 0xc6, 0xf5, 0xb7, 0x67, 0xf2, 0x3e, 0xeb, 0xd1, 0xa9, 0x9c, - 0x9e, 0x09, 0xb4, 0xca, 0x23, 0x24, 0xbd, 0xbe, 0xcd, 0x6b, 0xe8, 0x57, 0x71, 0x5e, 0xd8, 0x99, - 0x58, 0xa7, 0x77, 0xc0, 0xab, 0x76, 0xde, 0xa4, 0x4f, 0xad, 0xcb, 0x13, 0x1a, 0x8d, 0xd6, 0xd1, - 0x62, 0xd1, 0x6c, 0xda, 0x9f, 0x94, 0x03, 0x95, 0x48, 0x1c, 0x1f, 0xec, 0xa0, 0xfb, 0xf1, 0x91, - 0xba, 0xf0, 0xea, 0xef, 0x4b, 0xfe, 0x43, 0x36, 0xb4, 0xe7, 0x4c, 0x4d, 0xc1, 0x7a, 0x40, 0x91, - 0x1b, 0x5c, 0x9d, 0x20, 0x78, 0x37, 0xa2, 0x3f, 0x95, 0xf2, 0xd9, 0x88, 0x7b, 0xe3, 0xcf, 0x7f, - 0xba, 0x3a, 0xfb, 0x1b, 0x9d, 0x04, 0x9c, 0x9c, 0x9f, 0x7f, 0xb5, 0xbb, 0x8f, 0x37, 0x8b, 0xf4, - 0xde, 0x4e, 0xd2, 0x39, 0xef, 0xc0, 0xd9, 0xab, 0x34, 0x2f, 0x68, 0x53, 0x77, 0x7f, 0x4e, 0xbb, - 0xe5, 0x7f, 0xeb, 0x4f, 0x97, 0xf4, 0x4d, 0x14, 0xc4, 0x6f, 0x93, 0x10, 0xce, 0xce, 0xc4, 0xec, - 0x42, 0xd8, 0x7f, 0xcf, 0xa1, 0x33, 0xfd, 0x7e, 0xad, 0x6c, 0x47, 0x47, 0xc6, 0xfe, 0x12, 0x2f, - 0xe3, 0x1f, 0xd5, 0x36, 0x38, 0x7a, 0x98, 0xdd, 0x88, 0x31, 0x1b, 0x24, 0x56, 0xfb, 0x3a, 0x51, - 0xf2, 0x23, 0x50, 0x82, 0x41, 0xea, 0x58, 0x64, 0x0f, 0x44, 0x98, 0x2c, 0xb4, 0x7a, 0xcf, 0xc1, - 0x67, 0x3e, 0xdc, 0x68, 0xcb, 0x2f, 0xc0, 0x7f, 0x4c, 0x17, 0xc2, 0x8e, 0x17, 0x80, 0x2b, 0x4f, - 0x22, 0xcc, 0xbe, 0x70, 0xf6, 0xa0, 0x00, 0x98, 0x16, 0xc4, 0x90, 0xb2, 0x75, 0xab, 0x09, 0x41, - 0xa4, 0x63, 0x57, 0x7d, 0xfb, 0x2e, 0x4a, 0x6e, 0xc5, 0x8c, 0x94, 0xc9, 0x9e, 0x8b, 0x24, 0xc9, - 0x7f, 0x71, 0x3f, 0xd8, 0x31, 0x66, 0x32, 0xd9, 0xeb, 0x9f, 0xdf, 0x5c, 0x99, 0xaa, 0x1d, 0x6f, - 0x6f, 0xa3, 0x71, 0x59, 0x71, 0xaa, 0x43, 0xa5, 0xf8, 0x36, 0x7f, 0xc8, 0x7a, 0x56, 0xa3, 0xad, - 0x83, 0x3b, 0x3b, 0xb9, 0xe6, 0x59, 0xcc, 0x4a, 0x8b, 0xfb, 0xef, 0x5b, 0x91, 0x3d, 0xbc, 0x63, - 0x82, 0xd3, 0xec, 0xac, 0xf7, 0x65, 0x79, 0x14, 0x0f, 0xe2, 0x2b, 0x6a, 0x38, 0xf4, 0x7a, 0xa6, - 0xa0, 0x73, 0xd7, 0xaf, 0x22, 0x90, 0x0b, 0xee, 0x9b, 0x79, 0x1f, 0x02, 0x20, 0x01, 0x47, 0x15, - 0xb0, 0x79, 0x26, 0xa2, 0x42, 0x28, 0x0b, 0x3e, 0xeb, 0x15, 0x90, 0x81, 0xb9, 0x51, 0xe7, 0x61, - 0x7b, 0xcf, 0xf3, 0x69, 0x64, 0xd3, 0x21, 0x61, 0x33, 0x22, 0x71, 0xbc, 0x42, 0x4c, 0x29, 0xae, - 0xf8, 0xe0, 0x87, 0xc0, 0xc0, 0xbc, 0xa9, 0xd4, 0x33, 0x2b, 0x79, 0xf4, 0xd1, 0xac, 0x1a, 0xfe, - 0x6f, 0x2f, 0x8a, 0xc5, 0x45, 0xfd, 0xb0, 0x4f, 0x8f, 0xbe, 0x51, 0x49, 0xd5, 0x2f, 0x04, 0x29, - 0x89, 0xa9, 0x23, 0x6e, 0x52, 0x7a, 0x5f, 0xed, 0x36, 0x7b, 0xda, 0x12, 0x46, 0xbf, 0xbf, 0xd5, - 0x41, 0x3d, 0x67, 0x58, 0xe5, 0x61, 0x38, 0xd5, 0xee, 0xab, 0x9d, 0xb0, 0xe9, 0x75, 0xdf, 0xd5, - 0xe1, 0x19, 0x75, 0x50, 0x7b, 0x60, 0xe5, 0x69, 0xf8, 0xde, 0xc5, 0x33, 0xe8, 0x07, 0x7d, 0xbe, - 0xb7, 0xb9, 0x29, 0x56, 0xcf, 0x11, 0x1b, 0xff, 0xb8, 0xe6, 0xce, 0xc4, 0xa8, 0x5c, 0xc0, 0x82, - 0xe2, 0xe2, 0xe1, 0xdb, 0x06, 0x9c, 0x1e, 0x11, 0x01, 0x3e, 0xc8, 0xc5, 0xe2, 0xe7, 0x3d, 0xd9, - 0x7c, 0x72, 0xa4, 0x8d, 0x5c, 0xf0, 0xd3, 0xad, 0x4c, 0xe8, 0xf0, 0x16, 0xae, 0x6d, 0x71, 0xb9, - 0x8a, 0x93, 0xc5, 0x59, 0x44, 0x6a, 0x4c, 0x0a, 0x50, 0x9d, 0xca, 0x3c, 0x61, 0x88, 0x0d, 0x23, - 0x7e, 0x4b, 0x1b, 0xf2, 0xa2, 0x10, 0x59, 0xfe, 0xfb, 0x99, 0xb1, 0xdc, 0x60, 0x67, 0x93, 0x7d, - 0xba, 0x35, 0xff, 0xc4, 0x9f, 0xbf, 0xd8, 0x1f, 0xc5, 0x03, 0xa9, 0x6a, 0xa5, 0x6c, 0x65, 0xc0, - 0x80, 0x95, 0x15, 0x36, 0x3b, 0xee, 0xfc, 0x2f, 0x71, 0xb1, 0x3a, 0x93, 0x87, 0xe2, 0xa5, 0xb9, - 0x7c, 0xf3, 0xcd, 0x19, 0x68, 0x29, 0x0f, 0xa0, 0x37, 0xec, 0x47, 0xfc, 0x52, 0x7c, 0x30, 0x17, - 0x82, 0x8e, 0x6f, 0x19, 0xf4, 0xdc, 0x37, 0x3b, 0xc0, 0x80, 0xe3, 0x1a, 0x8a, 0x3e, 0x2f, 0xff, - 0x08, 0x90, 0xa7, 0x78, 0x1a, 0x93, 0x4c, 0xa9, 0xc6, 0x71, 0x1d, 0x09, 0xe1, 0xa8, 0xd4, 0xe3, - 0x2f, 0xd5, 0xd1, 0x7e, 0x4b, 0x7e, 0xad, 0xd4, 0xfb, 0x00, 0x34, 0xf4, 0x6e, 0x67, 0x4f, 0xfa, - 0xf6, 0x2e, 0x8c, 0x9e, 0xbd, 0x88, 0xd7, 0xfa, 0x5c, 0x1e, 0x1f, 0xba, 0xcf, 0xb3, 0xf9, 0xac, + 0xa5, 0xf3, 0xdf, 0x80, 0x00, 0x3d, 0x1e, 0x85, 0xcd, 0xdc, 0xae, 0x8d, 0xba, 0x10, 0x17, 0xdf, + 0x53, 0xd9, 0xd1, 0x21, 0x9a, 0x72, 0x25, 0xdf, 0xda, 0xa3, 0x61, 0x57, 0xb7, 0x6b, 0x0b, 0xe1, + 0xea, 0x94, 0x91, 0xc9, 0x9e, 0xb0, 0x33, 0x83, 0xbd, 0xc8, 0x4c, 0xa5, 0xd3, 0x16, 0x1c, 0xd9, + 0x91, 0x6e, 0xdc, 0x95, 0x3a, 0x28, 0xfb, 0x5c, 0x8b, 0xcd, 0x2d, 0x99, 0x5f, 0x32, 0x53, 0x29, + 0xfd, 0x25, 0xaf, 0xa6, 0xd1, 0xde, 0xf7, 0x1f, 0x49, 0xa7, 0x28, 0xd3, 0xf2, 0xe0, 0xac, 0x46, + 0x3d, 0x58, 0x03, 0x3a, 0x1c, 0xc3, 0xe6, 0xa8, 0xe9, 0xb6, 0x69, 0x6e, 0xb7, 0x94, 0x6e, 0x4f, + 0x64, 0xf5, 0x22, 0xe5, 0x3f, 0xb4, 0x3e, 0xd7, 0x9d, 0x5a, 0xba, 0x2d, 0xa4, 0x8a, 0xb7, 0xa0, + 0xae, 0xbc, 0xa6, 0xed, 0x5a, 0xde, 0xc5, 0xa5, 0xcc, 0x1e, 0xc8, 0xe1, 0x90, 0x3d, 0x60, 0x20, + 0xaf, 0xcb, 0x70, 0xf5, 0x40, 0xbc, 0x80, 0xa6, 0x81, 0x20, 0xf6, 0x74, 0x51, 0x53, 0x6f, 0xc3, + 0xcf, 0xc7, 0xd8, 0x51, 0xb0, 0x07, 0xd7, 0xa0, 0x93, 0x38, 0x2f, 0xc0, 0xbe, 0xa2, 0xe6, 0xcb, + 0x9b, 0x2c, 0x39, 0x06, 0xeb, 0xc5, 0x75, 0xf6, 0xeb, 0xfc, 0x4f, 0x3d, 0x6d, 0xea, 0x82, 0x47, + 0x11, 0x4c, 0x35, 0xa5, 0xc7, 0xc7, 0x75, 0xab, 0x9a, 0xcf, 0x9f, 0x52, 0xa8, 0x2a, 0x60, 0xe4, + 0x79, 0xbc, 0x50, 0x5d, 0x6b, 0x1b, 0x0b, 0x17, 0xef, 0xde, 0xfd, 0xf0, 0xdd, 0x71, 0x37, 0x5e, + 0xc2, 0xe1, 0x2e, 0x46, 0xb9, 0x0c, 0x6d, 0xd4, 0x56, 0x69, 0x67, 0xbd, 0x57, 0x34, 0x9b, 0x94, + 0x41, 0x03, 0xf2, 0xfc, 0xc1, 0x20, 0x98, 0x7c, 0x52, 0x83, 0xad, 0xa5, 0x47, 0x23, 0xf7, 0xca, + 0xb3, 0x1a, 0x87, 0x3c, 0xee, 0x56, 0xd0, 0x7f, 0x91, 0x5c, 0xbd, 0x82, 0xde, 0x41, 0xf2, 0x5b, + 0x55, 0xf5, 0x04, 0xb2, 0x6b, 0xa6, 0xdc, 0x58, 0x3d, 0x60, 0x23, 0x2d, 0x4b, 0xf4, 0x58, 0x27, + 0x20, 0x31, 0xb4, 0xd2, 0xa1, 0x94, 0x5d, 0x8d, 0x6a, 0xc6, 0xde, 0x2b, 0x61, 0x12, 0xb8, 0x47, + 0x40, 0xb5, 0x91, 0x83, 0xf9, 0xb3, 0xef, 0x28, 0x5f, 0x2d, 0xa1, 0xfd, 0x88, 0x78, 0x10, 0x2d, + 0xa7, 0x31, 0xc0, 0x5f, 0xed, 0x34, 0x4e, 0x71, 0xbf, 0x1c, 0xa8, 0xd3, 0x3d, 0x3e, 0x42, 0x99, + 0x74, 0x94, 0x9a, 0x3b, 0xbf, 0x1d, 0x39, 0x9b, 0xf4, 0x77, 0xa7, 0xe8, 0x31, 0x08, 0x75, 0x63, + 0x28, 0xd5, 0xec, 0x84, 0x41, 0xc4, 0x86, 0x6e, 0xc5, 0x4c, 0xd1, 0x2f, 0xa7, 0x51, 0xa4, 0xe5, + 0xa7, 0x79, 0xba, 0xde, 0x26, 0xa2, 0x10, 0x3a, 0x02, 0x94, 0x8a, 0x26, 0x53, 0x8b, 0x75, 0x8e, + 0x20, 0x41, 0x5b, 0x47, 0xb3, 0x5e, 0x35, 0xc0, 0xaf, 0x35, 0xb3, 0x17, 0xe7, 0x1d, 0xee, 0xe6, + 0x11, 0x5f, 0xd6, 0x53, 0x73, 0x35, 0xa3, 0x2b, 0x3d, 0x52, 0x36, 0xa8, 0x5a, 0xca, 0x69, 0xb6, + 0xa1, 0x77, 0x7e, 0x8f, 0xe6, 0x53, 0xab, 0x63, 0x66, 0x2d, 0x73, 0x32, 0x9d, 0xc3, 0x55, 0x73, + 0xf6, 0x8b, 0x77, 0x05, 0xa6, 0xff, 0x92, 0xbd, 0x98, 0x70, 0xd0, 0x69, 0xa1, 0x38, 0x4a, 0xf2, + 0xa3, 0xf9, 0x13, 0xc3, 0x92, 0x82, 0x23, 0x19, 0x50, 0x56, 0x99, 0xd3, 0x6a, 0x8f, 0xd1, 0xd8, + 0xb7, 0x2b, 0xd1, 0x96, 0x4b, 0x09, 0x48, 0xad, 0xe5, 0xe2, 0xc3, 0x13, 0xfc, 0x53, 0x7d, 0x71, + 0xe2, 0x9f, 0x49, 0x98, 0x65, 0x46, 0x39, 0x8f, 0x36, 0x8d, 0x94, 0x12, 0x9c, 0x3e, 0x99, 0xcc, + 0xb7, 0x0c, 0x46, 0x19, 0x09, 0x81, 0x79, 0x34, 0x77, 0x78, 0xaa, 0xd1, 0xb0, 0x04, 0x2e, 0xde, + 0x11, 0x48, 0xe6, 0xf6, 0x46, 0x14, 0x50, 0xb5, 0x8f, 0xc7, 0x59, 0x7d, 0x2a, 0x63, 0x53, 0x11, + 0xf0, 0x37, 0xa0, 0x51, 0x41, 0xfa, 0x8d, 0xc9, 0xac, 0xa5, 0x26, 0xe5, 0x6c, 0x80, 0xe2, 0x97, + 0x45, 0xe1, 0x4c, 0x05, 0xcb, 0x27, 0x93, 0x7d, 0x98, 0x51, 0xb5, 0xde, 0x55, 0x96, 0xc3, 0xe6, + 0x54, 0x29, 0x9f, 0xb6, 0x2e, 0x76, 0xa3, 0x6d, 0x90, 0x1d, 0xd6, 0xd5, 0x69, 0x85, 0x07, 0x06, + 0xd5, 0xad, 0x7a, 0x52, 0x2a, 0x99, 0xe0, 0x1d, 0x80, 0x47, 0x04, 0x72, 0x42, 0x18, 0x1a, 0xc0, + 0x6f, 0x21, 0x0c, 0x29, 0x88, 0x3f, 0x29, 0x88, 0xaf, 0xde, 0xbd, 0xed, 0xe4, 0x78, 0x07, 0xb7, + 0xa5, 0x05, 0x45, 0x77, 0x14, 0x72, 0xb2, 0x68, 0x9d, 0xff, 0xf3, 0xe4, 0x10, 0x90, 0xdf, 0x90, + 0x96, 0x77, 0x04, 0x0e, 0xfa, 0xba, 0x8c, 0x6f, 0x6e, 0xe5, 0xd1, 0x9d, 0x27, 0x90, 0x54, 0x07, + 0xf9, 0xe2, 0x9c, 0x16, 0x16, 0xf4, 0x4b, 0xcd, 0x11, 0xcb, 0x73, 0x82, 0x46, 0x19, 0x70, 0xe5, + 0xfb, 0xc5, 0x55, 0xca, 0xa9, 0xb6, 0x6d, 0xdb, 0x0d, 0x28, 0xea, 0xfc, 0x0c, 0x2f, 0x54, 0xf0, + 0xe9, 0xaa, 0xb5, 0xc8, 0xf3, 0xe8, 0xa6, 0x9e, 0xdf, 0xbe, 0x50, 0xe7, 0x69, 0x88, 0x2e, 0xf5, + 0xd4, 0xd2, 0x57, 0x39, 0xb2, 0x3a, 0x9f, 0x75, 0x28, 0x82, 0x74, 0x33, 0xa7, 0xc5, 0x84, 0x19, + 0x9f, 0x47, 0x7b, 0x43, 0x6d, 0xde, 0xc8, 0x41, 0xce, 0xfa, 0xa7, 0x65, 0xd0, 0x38, 0xc8, 0x76, + 0xd4, 0x46, 0xa5, 0x8c, 0xb8, 0x8d, 0x6c, 0x6f, 0xc8, 0x63, 0xc3, 0xee, 0xc0, 0x90, 0x2b, 0xe5, + 0xf4, 0xd4, 0x90, 0x13, 0xde, 0xdd, 0x41, 0x4f, 0x4a, 0x93, 0xd6, 0xa9, 0x8e, 0xce, 0x96, 0x3a, + 0x83, 0xde, 0xa1, 0x96, 0x1d, 0x62, 0x7c, 0x74, 0xb5, 0x06, 0x53, 0x1f, 0x62, 0xb5, 0xa4, 0x5f, + 0x35, 0xeb, 0x9a, 0xec, 0x9c, 0x8e, 0xb6, 0xad, 0xa3, 0x70, 0x5d, 0x03, 0x6d, 0xeb, 0xe3, 0xf0, + 0x5c, 0xe6, 0xc5, 0xf9, 0xf6, 0xd7, 0x8d, 0xa2, 0x9c, 0xce, 0x51, 0xc7, 0x9d, 0x7e, 0x54, 0xfc, + 0xae, 0x8c, 0x4a, 0xa9, 0xdd, 0x71, 0x89, 0x17, 0xd9, 0xad, 0xe8, 0x5f, 0x48, 0x1b, 0xf8, 0xe9, + 0xff, 0x2a, 0x9d, 0x3f, 0x19, 0x1d, 0x6a, 0x72, 0xad, 0x19, 0xef, 0x89, 0x21, 0x96, 0x88, 0xf9, + 0xe5, 0x18, 0x97, 0x54, 0x7d, 0x74, 0x98, 0x53, 0xde, 0x18, 0xcf, 0xd2, 0x36, 0xca, 0x03, 0xe5, + 0xf3, 0x2c, 0xde, 0x16, 0x17, 0xd0, 0x94, 0xab, 0xf4, 0x26, 0x9d, 0x3d, 0x63, 0xcd, 0x93, 0xaa, + 0x16, 0xd0, 0x71, 0x12, 0xa5, 0x6c, 0xfc, 0xdc, 0x74, 0x0b, 0x23, 0xfc, 0x85, 0x5b, 0xd8, 0x46, + 0xc5, 0xca, 0xc0, 0xe4, 0xe7, 0x8d, 0xeb, 0xd9, 0x63, 0x2f, 0x30, 0xdc, 0xb1, 0xed, 0x7b, 0x83, + 0x28, 0xb4, 0x03, 0x83, 0xfe, 0xf1, 0x4e, 0x89, 0x85, 0xaa, 0x91, 0x6f, 0x05, 0x76, 0x38, 0x1c, + 0xa0, 0x74, 0xa0, 0x2e, 0xb2, 0xce, 0xb7, 0x47, 0xde, 0xc8, 0x72, 0xed, 0xe1, 0x70, 0x60, 0x07, + 0xe3, 0x90, 0xfe, 0xc9, 0xdd, 0x15, 0xcb, 0x0e, 0x9c, 0xc0, 0xb2, 0x43, 0xdf, 0xb5, 0x83, 0x70, + 0x40, 0xff, 0x64, 0xb9, 0x61, 0x87, 0x03, 0x1f, 0x95, 0x6e, 0x68, 0x8c, 0xec, 0xb1, 0xba, 0xc8, + 0x9a, 0x91, 0x31, 0xb6, 0x47, 0xce, 0x10, 0xe0, 0x01, 0x53, 0x5d, 0x15, 0x2c, 0x6f, 0x3c, 0x32, + 0x30, 0xc8, 0xc0, 0x4b, 0x5c, 0x20, 0x33, 0xb6, 0x87, 0x41, 0xe4, 0xba, 0xb6, 0xe3, 0x8f, 0x0d, + 0x75, 0x53, 0x7b, 0x3a, 0x76, 0xe8, 0x0e, 0x00, 0x7c, 0xe8, 0x1a, 0x20, 0xc8, 0x1d, 0x8e, 0xf5, + 0x4d, 0x56, 0xdb, 0x9e, 0x1b, 0x82, 0x1a, 0x7f, 0xe0, 0xbf, 0x44, 0xf9, 0x30, 0x34, 0xe4, 0x55, + 0x56, 0x86, 0xa8, 0xf5, 0x8c, 0xc0, 0x76, 0x43, 0x37, 0x1a, 0xda, 0x43, 0xdf, 0xe0, 0x8b, 0xe2, + 0x00, 0xae, 0x03, 0xdb, 0x07, 0xfd, 0xf2, 0xaa, 0xf9, 0xe2, 0x82, 0x63, 0xb6, 0xef, 0x87, 0x28, + 0xf6, 0xc2, 0x81, 0xba, 0x6a, 0x54, 0xc6, 0xce, 0x18, 0xe0, 0x46, 0xc3, 0x80, 0xc8, 0x1a, 0xeb, + 0xab, 0xae, 0x75, 0xc0, 0x14, 0x77, 0x3c, 0x44, 0x1f, 0xc7, 0x75, 0xd5, 0x55, 0xb2, 0xc1, 0x67, + 0x88, 0xbe, 0x3d, 0xc6, 0x40, 0xb8, 0x06, 0x43, 0x75, 0xd5, 0x6c, 0x85, 0x47, 0xc7, 0xc0, 0x60, + 0x84, 0x1f, 0xba, 0xf6, 0x68, 0x14, 0xb9, 0x8e, 0xed, 0x8e, 0x3c, 0x43, 0xdd, 0x24, 0x7c, 0xcf, + 0x76, 0x86, 0x21, 0x08, 0xf5, 0x40, 0xd6, 0x50, 0x5d, 0x14, 0x0f, 0x20, 0x45, 0x60, 0x1e, 0x78, + 0xa3, 0x35, 0xa1, 0x3f, 0x80, 0x84, 0x5e, 0xba, 0x3e, 0xd0, 0xf1, 0x0d, 0x75, 0x53, 0x62, 0x72, + 0x1c, 0x97, 0x60, 0x42, 0xf4, 0xc4, 0xa6, 0x31, 0x8d, 0x20, 0x6f, 0x1a, 0x4b, 0xaa, 0x40, 0xef, + 0x30, 0x21, 0x89, 0x92, 0xe0, 0x23, 0x34, 0x70, 0x02, 0xe6, 0x2a, 0xdd, 0x1c, 0x4d, 0x6b, 0x68, + 0xbb, 0x03, 0xd7, 0xe8, 0xaa, 0x54, 0x55, 0x4e, 0xa2, 0x75, 0x87, 0x40, 0x8c, 0xb9, 0x51, 0xa9, + 0x47, 0xd0, 0x48, 0x3f, 0xc0, 0x70, 0xa1, 0x17, 0xbc, 0x41, 0x34, 0x23, 0x94, 0xc6, 0x40, 0x99, + 0x6f, 0xea, 0x4d, 0x43, 0x43, 0xaf, 0x01, 0x64, 0x9d, 0x40, 0x1f, 0x5d, 0xa0, 0x04, 0x16, 0x40, + 0x73, 0x86, 0x1e, 0x90, 0xf4, 0x22, 0x17, 0x8a, 0x06, 0xf9, 0xaa, 0x9b, 0xa4, 0x01, 0xba, 0x33, + 0x1c, 0x8d, 0xf8, 0x16, 0x06, 0x09, 0xe9, 0x2a, 0xda, 0x07, 0xfe, 0xdc, 0xb1, 0x6c, 0x3f, 0x08, + 0x80, 0xe7, 0x98, 0x14, 0xd8, 0xe3, 0x07, 0x06, 0xb9, 0xc6, 0xcd, 0x0b, 0xc6, 0x50, 0x0d, 0x37, + 0x18, 0xbe, 0x04, 0xf6, 0xd0, 0x10, 0x79, 0xd5, 0x3a, 0x34, 0x72, 0x49, 0x51, 0xbd, 0x90, 0xd4, + 0xd3, 0x75, 0x59, 0x3d, 0xe9, 0xa6, 0x15, 0x66, 0x40, 0x4a, 0x67, 0x87, 0xe1, 0x1d, 0xac, 0xc2, + 0x1f, 0x12, 0xe3, 0xc7, 0xd4, 0x48, 0xde, 0x14, 0x52, 0x63, 0x0c, 0x31, 0x22, 0x44, 0x87, 0xe1, + 0x8a, 0x9a, 0x0d, 0x08, 0x56, 0xe8, 0xfa, 0x86, 0xba, 0x95, 0xaa, 0x1e, 0xba, 0x04, 0x71, 0x10, + 0xbc, 0x09, 0x61, 0xbb, 0x84, 0xc7, 0x68, 0x84, 0xb6, 0x60, 0x23, 0x80, 0xf0, 0x95, 0xc1, 0x59, + 0xf4, 0x6c, 0xd5, 0x8b, 0x75, 0x25, 0x57, 0xe3, 0x59, 0x16, 0xd0, 0xa4, 0x4c, 0x06, 0x9d, 0x67, + 0x53, 0x38, 0xf1, 0xbc, 0x30, 0xf0, 0xfc, 0x46, 0x6c, 0x6e, 0xe1, 0x56, 0x4a, 0x37, 0xe1, 0x9b, + 0xc1, 0x6b, 0xcf, 0x7d, 0x3f, 0x7a, 0xed, 0xbf, 0x0f, 0xf0, 0xe2, 0xba, 0xf4, 0xe6, 0xfa, 0x78, + 0x75, 0x5d, 0x7a, 0xe7, 0x5a, 0x97, 0xaa, 0xdd, 0xe0, 0xaf, 0xbd, 0xf3, 0x8b, 0x67, 0x26, 0xfb, + 0x26, 0x38, 0x45, 0xe9, 0x9b, 0x94, 0x43, 0xea, 0xb9, 0xc1, 0xb6, 0xe8, 0x35, 0x5d, 0xd2, 0x10, + 0x62, 0xc1, 0xbf, 0x9a, 0x53, 0x5a, 0x93, 0xe0, 0x51, 0xb4, 0xb2, 0xbc, 0xd1, 0x68, 0x6e, 0x79, + 0x01, 0xd8, 0xe7, 0xbb, 0x1e, 0x2c, 0xc1, 0x1a, 0x8c, 0x2c, 0x0f, 0x52, 0xf3, 0x60, 0xca, 0x23, + 0x7a, 0x19, 0x8c, 0xee, 0x2c, 0xcf, 0x1b, 0x40, 0x72, 0xd4, 0x2a, 0x0c, 0x86, 0x81, 0x67, 0x50, + 0x83, 0x41, 0x30, 0x0a, 0x87, 0xa8, 0x35, 0xb8, 0xcd, 0x8a, 0xe0, 0xd4, 0xc0, 0xa0, 0xd4, 0x28, + 0xc1, 0x18, 0xdc, 0xea, 0x8e, 0xa1, 0x18, 0x25, 0x14, 0xab, 0x84, 0x22, 0x41, 0xe0, 0xfa, 0x79, + 0x4d, 0xf8, 0x48, 0x9c, 0x46, 0x10, 0x38, 0x23, 0xe4, 0x92, 0xc3, 0x74, 0x83, 0x70, 0x4c, 0xbc, + 0x86, 0x57, 0x08, 0x14, 0x20, 0x34, 0xf0, 0x3d, 0xc7, 0x77, 0xa9, 0x96, 0x80, 0x70, 0x1d, 0xfe, + 0x32, 0x2a, 0xba, 0x37, 0xde, 0x2d, 0xdd, 0x9b, 0x9e, 0xd1, 0x5b, 0x51, 0xa3, 0xbb, 0x5b, 0xb2, + 0xbb, 0xc5, 0x95, 0xf8, 0xfb, 0x79, 0x0d, 0x96, 0x81, 0xbf, 0x35, 0x5e, 0x39, 0xf0, 0x0b, 0xe8, + 0x53, 0x76, 0x61, 0xa4, 0xac, 0x1a, 0x52, 0x0c, 0x76, 0xe4, 0x00, 0xea, 0x90, 0x9c, 0xfd, 0x38, + 0x00, 0x11, 0x64, 0x25, 0x21, 0x1a, 0x7b, 0xd6, 0x38, 0x90, 0x7f, 0x73, 0xfc, 0x33, 0xea, 0xc5, + 0xc6, 0x38, 0xb8, 0xa3, 0x5e, 0x46, 0x1d, 0x97, 0x1a, 0xaa, 0xb8, 0xe6, 0x47, 0x47, 0x0a, 0x1d, + 0x7b, 0x38, 0xf6, 0x41, 0x37, 0xbc, 0xd1, 0xc0, 0x09, 0x3c, 0x50, 0x00, 0xa7, 0xee, 0x52, 0xc8, + 0xf0, 0x46, 0x39, 0x3d, 0xeb, 0x0a, 0x43, 0x55, 0x3c, 0x36, 0x56, 0x49, 0xb9, 0x54, 0x55, 0xd2, + 0xaf, 0x3f, 0x6f, 0x92, 0xff, 0xaf, 0x61, 0xbf, 0xbf, 0x86, 0x8d, 0x9c, 0x27, 0x2b, 0xd8, 0xaf, + 0x17, 0xfb, 0xaf, 0xd5, 0xaf, 0xdf, 0x41, 0x8b, 0x3b, 0x34, 0x8b, 0x96, 0x13, 0xea, 0xee, 0x8f, + 0x02, 0x88, 0x77, 0x39, 0x96, 0x21, 0x0a, 0xa0, 0x38, 0xaa, 0x21, 0x9a, 0x05, 0xc8, 0x95, 0xe0, + 0xc4, 0x47, 0x57, 0x03, 0x9b, 0xc3, 0xc9, 0xe0, 0x12, 0x81, 0xdf, 0xe5, 0x88, 0x8f, 0x8b, 0x6f, + 0x50, 0x1e, 0x62, 0x8c, 0xdf, 0x51, 0xb8, 0x1b, 0xcb, 0x52, 0xf2, 0xf2, 0xdc, 0xf2, 0x0a, 0x8e, + 0x1e, 0x49, 0x03, 0xc0, 0xe2, 0x21, 0x08, 0x0c, 0x19, 0xa3, 0x86, 0x23, 0xfd, 0xc0, 0x35, 0x60, + 0x96, 0xcf, 0x05, 0x50, 0x1a, 0x8e, 0xc3, 0x94, 0xaa, 0x71, 0x7e, 0x82, 0xe7, 0x10, 0x0d, 0x06, + 0xd0, 0x38, 0x5d, 0xee, 0xf3, 0xd5, 0x93, 0x7f, 0xdf, 0x78, 0x40, 0xe3, 0xca, 0xf3, 0x80, 0x17, + 0x90, 0xbc, 0xc4, 0xb0, 0xe1, 0x98, 0x92, 0x98, 0x01, 0xc1, 0x42, 0xae, 0xc5, 0x60, 0xfd, 0x77, + 0xc8, 0x5c, 0x5c, 0x55, 0x6c, 0x53, 0x12, 0x14, 0x5c, 0x01, 0xe9, 0x4b, 0x8c, 0x40, 0x5a, 0x45, + 0x94, 0x42, 0xdb, 0x19, 0x68, 0xf0, 0x8e, 0x91, 0xe2, 0x52, 0x02, 0xcd, 0x2c, 0x19, 0x5e, 0x22, + 0x0e, 0x23, 0x43, 0x71, 0x87, 0x20, 0x6e, 0x40, 0x98, 0x01, 0x9b, 0x91, 0xcd, 0x63, 0x78, 0x57, + 0xdc, 0x12, 0x57, 0x82, 0xee, 0x41, 0x31, 0x06, 0x97, 0x94, 0x94, 0xf9, 0xc4, 0x02, 0xe6, 0x0b, + 0xb1, 0xc2, 0xd3, 0xe4, 0x5e, 0xba, 0x1c, 0xc9, 0x28, 0xd0, 0xa3, 0x43, 0xc0, 0x58, 0x82, 0x17, + 0x3e, 0x01, 0x75, 0x46, 0xd4, 0x33, 0x60, 0xd2, 0x1d, 0x26, 0xdd, 0xa7, 0x72, 0xee, 0x3a, 0x7c, + 0x43, 0x81, 0x77, 0x40, 0x00, 0x86, 0x44, 0x22, 0x3d, 0xf2, 0xa4, 0x0a, 0x18, 0x8c, 0xf9, 0x01, + 0xc0, 0xdf, 0xc9, 0x3a, 0x70, 0x03, 0x75, 0x23, 0xbe, 0x13, 0x47, 0x02, 0xf9, 0x48, 0x86, 0xca, + 0xb8, 0xc2, 0x30, 0xe9, 0x1a, 0xba, 0x40, 0xf7, 0xb5, 0xe7, 0x50, 0x93, 0x21, 0xa3, 0x1e, 0xb8, + 0x04, 0x66, 0xc4, 0x94, 0x53, 0x7f, 0xf7, 0x12, 0xe0, 0x03, 0xf9, 0x4a, 0xbc, 0x42, 0x43, 0x4a, + 0x27, 0xf8, 0x91, 0x87, 0xe3, 0x5a, 0x52, 0x2e, 0x94, 0x06, 0x2c, 0xe0, 0x31, 0xbf, 0x52, 0x96, + 0xcd, 0xa8, 0x8d, 0xe8, 0x39, 0x0c, 0xe9, 0x39, 0xf4, 0xaf, 0x5c, 0x19, 0xf6, 0x5f, 0x7b, 0xde, + 0x7b, 0xc2, 0xff, 0x0a, 0x43, 0x8e, 0x98, 0xf2, 0x20, 0xbc, 0xc4, 0x33, 0x32, 0x44, 0x14, 0x8f, + 0x79, 0x1c, 0xf9, 0xcc, 0x64, 0xd0, 0xfd, 0xaf, 0x14, 0xbd, 0x59, 0x65, 0xd5, 0xd2, 0x50, 0x4b, + 0x6b, 0x83, 0x4b, 0x25, 0xc2, 0x52, 0xa4, 0x90, 0xef, 0x95, 0x92, 0xf5, 0x65, 0x25, 0xfd, 0x90, + 0xc0, 0x2b, 0x9d, 0xa8, 0xe9, 0x8a, 0xd6, 0x9f, 0x2b, 0x12, 0xf9, 0x65, 0xa5, 0x01, 0x40, 0x0d, + 0x6e, 0x4d, 0x2a, 0xc6, 0x1b, 0xd0, 0x30, 0x1a, 0x90, 0xfa, 0x0d, 0x5c, 0xd2, 0x58, 0xc2, 0x0c, + 0xaa, 0x18, 0x72, 0x82, 0x34, 0xa4, 0x67, 0x97, 0x9f, 0x29, 0x55, 0xc1, 0xf3, 0x55, 0x69, 0x01, + 0x97, 0x75, 0xb3, 0x40, 0x3e, 0xaa, 0xad, 0xa5, 0x32, 0x21, 0x6d, 0x55, 0x57, 0xda, 0xce, 0x2e, + 0x2b, 0xd3, 0xd3, 0xc6, 0x28, 0x4d, 0x13, 0x95, 0xa1, 0x34, 0x9d, 0x21, 0xcd, 0x51, 0x5c, 0x96, + 0x74, 0x85, 0xd7, 0xd3, 0xb5, 0x15, 0xae, 0x63, 0x40, 0x7c, 0x0e, 0x40, 0x0b, 0xab, 0x2a, 0x65, + 0xb0, 0xfc, 0xe0, 0xa9, 0x07, 0x2e, 0x0f, 0x59, 0x1d, 0x7d, 0x1e, 0x2b, 0x60, 0x23, 0xa5, 0xac, + 0x9e, 0x61, 0xfa, 0x84, 0x0c, 0x8d, 0xc2, 0xb3, 0x04, 0x8f, 0xa5, 0xac, 0x75, 0xd5, 0x23, 0x00, + 0x57, 0xb4, 0x2f, 0x1a, 0x50, 0xb6, 0x84, 0x2b, 0x6b, 0xda, 0x7b, 0xcf, 0xbb, 0xe2, 0xaa, 0x4a, + 0x9c, 0xb4, 0x28, 0xd3, 0x90, 0xe5, 0xd0, 0x1c, 0xbf, 0x1e, 0xbe, 0x1f, 0xbe, 0x26, 0x8d, 0xf7, + 0x4c, 0x77, 0xfc, 0xd2, 0x37, 0x39, 0x25, 0x34, 0xc1, 0x2b, 0xe4, 0x5f, 0xb5, 0x57, 0xaa, 0xf6, + 0xeb, 0xef, 0xc3, 0xc3, 0x7a, 0xd8, 0x6f, 0x68, 0xfa, 0xaf, 0x87, 0x97, 0x60, 0xea, 0x18, 0x35, + 0xa8, 0x85, 0x51, 0xfa, 0xe6, 0xf0, 0x3d, 0x20, 0x7b, 0x26, 0x27, 0xca, 0x26, 0x22, 0xa7, 0xe9, + 0xb9, 0xaf, 0x1b, 0x25, 0x9e, 0x8b, 0xce, 0xef, 0xc3, 0x2b, 0xea, 0x5e, 0x61, 0xab, 0x96, 0xc3, + 0x9a, 0xca, 0x67, 0x0e, 0xc8, 0x3f, 0xb9, 0x26, 0xb3, 0x08, 0x37, 0x12, 0x26, 0xf8, 0x66, 0x06, + 0xb6, 0x4f, 0x5a, 0x1d, 0x9a, 0x24, 0x05, 0x7e, 0x90, 0x1a, 0x4d, 0x75, 0x74, 0x21, 0x4b, 0x1e, + 0x99, 0x64, 0x7c, 0xc4, 0x61, 0xdf, 0x44, 0x13, 0x9e, 0xe5, 0x8c, 0xa9, 0x0c, 0xca, 0x0b, 0x85, + 0xa0, 0x76, 0x24, 0x08, 0x80, 0x75, 0x59, 0x25, 0x06, 0x54, 0x1b, 0x4a, 0xa1, 0x83, 0x3c, 0x5c, + 0x58, 0x5b, 0x4d, 0xca, 0xb0, 0x0d, 0xf9, 0xe4, 0x50, 0x3b, 0xaa, 0x0d, 0xed, 0x90, 0x86, 0x70, + 0x4d, 0xa5, 0x55, 0x43, 0x93, 0xe4, 0x64, 0x42, 0x22, 0x50, 0x8f, 0xab, 0xd0, 0x84, 0xd9, 0x41, + 0x1b, 0x4c, 0xbc, 0xbc, 0x1f, 0xbc, 0x01, 0xb2, 0x12, 0x29, 0x9f, 0xf0, 0xa4, 0x29, 0x19, 0x65, + 0xbf, 0x34, 0x11, 0x00, 0x9c, 0x31, 0x29, 0x26, 0x91, 0x41, 0x1e, 0x13, 0xc5, 0x36, 0xd9, 0xd9, + 0x98, 0xc8, 0x21, 0x8b, 0x1a, 0x49, 0x3c, 0x46, 0xd4, 0x03, 0x66, 0x4e, 0x33, 0x5e, 0x02, 0x45, + 0xba, 0xcd, 0x84, 0x0e, 0xae, 0x98, 0xa2, 0xc1, 0x25, 0x11, 0x4b, 0x76, 0x45, 0xb4, 0x0c, 0x0c, + 0x3d, 0x62, 0xc5, 0xdd, 0x57, 0x0f, 0xa2, 0x6d, 0xd6, 0xf6, 0x70, 0x0e, 0xcd, 0xa2, 0x59, 0x25, + 0xdc, 0x17, 0x79, 0x4d, 0x84, 0x5c, 0x9a, 0xe4, 0x0d, 0x31, 0x93, 0x71, 0x79, 0xe2, 0x4c, 0x1e, + 0x7d, 0x10, 0x24, 0xd0, 0x67, 0x9a, 0x44, 0x39, 0xc1, 0x1c, 0xf3, 0x46, 0x9a, 0x0e, 0x40, 0xcf, + 0x30, 0x79, 0x18, 0x5b, 0xac, 0x98, 0x60, 0xe0, 0x88, 0x3e, 0xea, 0x85, 0x40, 0x68, 0xf2, 0x42, + 0x48, 0xa0, 0x37, 0xa6, 0xb5, 0xa4, 0xaf, 0x08, 0xf9, 0x5c, 0xc8, 0xf3, 0x17, 0xe8, 0x3f, 0xe6, + 0xfc, 0x01, 0xda, 0x86, 0x89, 0x47, 0x16, 0x4d, 0x97, 0x39, 0x3c, 0x26, 0xc6, 0x03, 0xf3, 0x03, + 0x3d, 0x22, 0xcd, 0xbc, 0x06, 0x9f, 0xdf, 0x78, 0xe4, 0x45, 0x01, 0x3d, 0x98, 0x63, 0x4a, 0x35, + 0xa6, 0x91, 0x6d, 0x9a, 0xb3, 0xdb, 0x8e, 0xc7, 0x53, 0x98, 0x81, 0x4b, 0xf3, 0x79, 0x9a, 0x12, + 0x8d, 0xc3, 0x4b, 0x46, 0x31, 0x54, 0xd3, 0x4a, 0x32, 0x6c, 0x0a, 0x6f, 0x3c, 0x39, 0x33, 0x68, + 0x0a, 0x47, 0x96, 0x04, 0x5f, 0x80, 0xc6, 0x2a, 0x6a, 0xcc, 0x5d, 0x39, 0xab, 0xa5, 0xb9, 0x22, + 0xc0, 0x92, 0xa7, 0x02, 0xc1, 0x23, 0x2f, 0xa1, 0x90, 0x48, 0x5d, 0xbc, 0xb9, 0x1c, 0x93, 0xc7, + 0x93, 0x77, 0x9a, 0x6c, 0x1a, 0x0a, 0x0d, 0xc9, 0x07, 0xc2, 0xc4, 0xa2, 0x0a, 0xc4, 0x6e, 0x58, + 0x74, 0x89, 0xab, 0xa5, 0xaa, 0x7d, 0xf5, 0x80, 0xb8, 0xeb, 0x7c, 0x7e, 0x23, 0x63, 0xf0, 0x70, + 0x6e, 0x49, 0xae, 0x5b, 0x43, 0x8b, 0xb8, 0x8e, 0x1b, 0x65, 0x68, 0xc0, 0x9a, 0xf8, 0x08, 0xb4, + 0x24, 0x63, 0xdd, 0x41, 0xe2, 0xf2, 0x2a, 0x03, 0x2e, 0x80, 0xe9, 0x30, 0x97, 0x41, 0x24, 0x26, + 0xee, 0x7c, 0xe3, 0xa5, 0x07, 0x97, 0x3d, 0x08, 0x39, 0x59, 0x9f, 0xff, 0xd8, 0x1e, 0x63, 0x38, + 0xe2, 0xf6, 0x34, 0x81, 0x75, 0x60, 0x64, 0x40, 0x8d, 0xac, 0x67, 0x4e, 0x4b, 0x1b, 0x08, 0x1d, + 0xf4, 0x51, 0x33, 0x94, 0x9c, 0x87, 0xb0, 0x87, 0x9f, 0xd7, 0xcc, 0x01, 0x54, 0xf8, 0x68, 0xe0, + 0x0e, 0x09, 0x59, 0x92, 0xd8, 0xd0, 0x52, 0x02, 0x0e, 0x78, 0xc2, 0x3f, 0x48, 0x3c, 0xb9, 0x76, + 0x10, 0x0c, 0x3e, 0x97, 0x2a, 0xf5, 0x63, 0xda, 0x52, 0x2a, 0x58, 0xf7, 0xca, 0x1b, 0xdc, 0x79, + 0x83, 0xd7, 0xce, 0x7b, 0xe7, 0xb3, 0x5a, 0x90, 0xec, 0xd1, 0x8a, 0x64, 0x3d, 0x17, 0x24, 0x3e, + 0x50, 0xac, 0xa5, 0x85, 0x0f, 0x25, 0x9d, 0x90, 0xa3, 0x23, 0x24, 0x33, 0xa7, 0x45, 0x01, 0x12, + 0xc6, 0xd8, 0x20, 0x71, 0xc2, 0x14, 0x29, 0x35, 0x1d, 0xe6, 0xd0, 0x9c, 0x10, 0xaa, 0x43, 0x8a, + 0x45, 0xc9, 0xd7, 0x90, 0xb4, 0x2a, 0xf4, 0x2d, 0x6a, 0x68, 0x51, 0x76, 0x07, 0xbc, 0xb9, 0x5c, + 0x32, 0x39, 0xec, 0x60, 0x71, 0x2e, 0x1f, 0x0c, 0xe2, 0x76, 0xa5, 0xee, 0x96, 0x7c, 0xa0, 0x32, + 0x64, 0x70, 0xd6, 0x88, 0xe0, 0x06, 0xd4, 0xd1, 0x67, 0xb6, 0xe2, 0xe6, 0xe7, 0x35, 0xfe, 0xfa, + 0x96, 0x7c, 0xb1, 0xe4, 0x83, 0x45, 0x0f, 0xfe, 0x67, 0x3d, 0x55, 0xbd, 0x2c, 0x97, 0xee, 0x34, + 0x53, 0xf8, 0x68, 0x66, 0x76, 0x9b, 0x88, 0x59, 0x4f, 0xdc, 0x89, 0x4d, 0xba, 0x58, 0xd0, 0x49, + 0xb6, 0x78, 0xdb, 0x2e, 0x63, 0xae, 0xc0, 0x39, 0x38, 0x21, 0x4d, 0xaa, 0xe9, 0xe6, 0x92, 0xdb, + 0x73, 0xc6, 0x21, 0x8b, 0xd7, 0x0d, 0x86, 0x1c, 0xa9, 0xf9, 0x1d, 0x2e, 0x65, 0xe4, 0x0f, 0x28, + 0x1c, 0xaa, 0x0e, 0xf0, 0x6c, 0x63, 0x6f, 0x34, 0xe6, 0x90, 0x81, 0xa6, 0x81, 0x61, 0x39, 0xdc, + 0xd2, 0x77, 0x65, 0x98, 0x43, 0xeb, 0x56, 0x11, 0xda, 0x8f, 0xcb, 0x6e, 0x57, 0x21, 0xc5, 0xf5, + 0xd1, 0x30, 0xa4, 0x90, 0xce, 0x43, 0xd7, 0x20, 0xaa, 0xb1, 0x6b, 0xdd, 0xcb, 0xe1, 0x1b, 0x65, + 0xb2, 0x7d, 0xd5, 0xf1, 0x91, 0x0e, 0x1a, 0x6e, 0xd9, 0x51, 0x8d, 0x7c, 0xa5, 0x30, 0x31, 0xc2, + 0xab, 0xaa, 0x4a, 0xe2, 0x7b, 0xf9, 0x08, 0x55, 0x8a, 0xf6, 0xaa, 0x9b, 0xe4, 0xce, 0x65, 0xc5, + 0xae, 0x23, 0xfc, 0xd4, 0x44, 0xab, 0x0e, 0x57, 0xe4, 0x63, 0x07, 0xee, 0x40, 0x66, 0x9d, 0xcc, + 0x29, 0x0d, 0x4a, 0x0f, 0x5b, 0xf6, 0x54, 0x63, 0xd6, 0xde, 0xa5, 0x04, 0x75, 0xfb, 0x63, 0xed, + 0x34, 0x1c, 0xdd, 0x5e, 0x8e, 0x73, 0xa5, 0xc6, 0x05, 0xf1, 0x2d, 0x5d, 0xf8, 0xab, 0x36, 0xa5, + 0xeb, 0x24, 0xa2, 0x1d, 0x5b, 0xe8, 0xdb, 0xf4, 0x2e, 0xca, 0xe8, 0x3c, 0x52, 0x9c, 0x6e, 0xf2, + 0xd9, 0x6e, 0x6f, 0x7e, 0x35, 0x5b, 0xde, 0x6e, 0xf8, 0x38, 0xf1, 0x99, 0xe8, 0xef, 0x32, 0x51, + 0xdc, 0x66, 0x1b, 0x63, 0x91, 0xce, 0x6f, 0xd7, 0x62, 0x53, 0xd8, 0x37, 0xa2, 0x78, 0x95, 0x08, + 0x7a, 0xfc, 0xe3, 0xc3, 0x0f, 0x0b, 0xb4, 0xd8, 0x4f, 0x75, 0x73, 0x83, 0x8e, 0x33, 0xbc, 0x8e, + 0x17, 0x42, 0x1f, 0x19, 0x39, 0xeb, 0xef, 0x08, 0xb6, 0x98, 0x7d, 0x75, 0x56, 0xed, 0xb9, 0xf7, + 0xa7, 0x74, 0xda, 0xac, 0xb1, 0x2c, 0xdd, 0x53, 0xf1, 0xfa, 0x8b, 0x9e, 0xd9, 0xa3, 0xa3, 0x42, + 0xaf, 0xde, 0xbd, 0x35, 0xd4, 0x1e, 0x99, 0x58, 0xd8, 0xc6, 0xdb, 0x84, 0x3e, 0x7e, 0x34, 0xee, + 0xa3, 0xb8, 0x30, 0x22, 0x23, 0x89, 0x8b, 0x22, 0x11, 0x7c, 0x60, 0xb6, 0x58, 0x89, 0x0d, 0x9d, + 0x60, 0xa3, 0x43, 0x98, 0xc5, 0x2a, 0xce, 0x8d, 0x2d, 0xa0, 0xd9, 0x04, 0xa1, 0xd7, 0x37, 0xab, + 0x11, 0x67, 0xb3, 0x99, 0xb0, 0x69, 0xe3, 0xfa, 0xdb, 0x33, 0x79, 0x9f, 0xf5, 0xe8, 0x54, 0x4e, + 0xcf, 0x04, 0x5a, 0xe5, 0x11, 0x92, 0x5e, 0xdf, 0xe6, 0x35, 0xf4, 0xab, 0x38, 0x2f, 0xec, 0x4c, + 0xac, 0xd3, 0x3b, 0xe0, 0x55, 0x3b, 0x6f, 0xd2, 0xa7, 0xd6, 0xe5, 0x09, 0x8d, 0x46, 0xeb, 0x68, + 0xb1, 0x68, 0x36, 0xed, 0x4f, 0xca, 0x81, 0x4a, 0x24, 0x8e, 0x0f, 0x76, 0xd0, 0xfd, 0xf8, 0x48, + 0x5d, 0x78, 0xf5, 0xf7, 0x25, 0xff, 0x21, 0x1b, 0xda, 0x73, 0xa6, 0xa6, 0x60, 0x3d, 0xa0, 0xc8, + 0x0d, 0xae, 0x4e, 0x10, 0xbc, 0x1b, 0xd1, 0x9f, 0x4a, 0xf9, 0x6c, 0xc4, 0xbd, 0xf1, 0xe7, 0x3f, + 0x5d, 0x9d, 0xfd, 0x8d, 0x0e, 0xff, 0x4d, 0xce, 0xcf, 0xbf, 0xda, 0xdd, 0xc7, 0x9b, 0x45, 0x7a, + 0x6f, 0x27, 0xe9, 0x9c, 0x77, 0xe0, 0xec, 0x55, 0x9a, 0x17, 0xb4, 0xa9, 0xbb, 0x3f, 0xa7, 0xdd, + 0xf2, 0xbf, 0xf5, 0xa7, 0x4b, 0xfa, 0xec, 0x0a, 0xe2, 0xb7, 0x49, 0x08, 0x67, 0x67, 0x62, 0x76, + 0x21, 0xec, 0xbf, 0xe7, 0xd0, 0x99, 0x7e, 0xbf, 0x56, 0xb6, 0xa3, 0x23, 0x63, 0x7f, 0x89, 0x97, + 0xf1, 0x8f, 0x6a, 0x1b, 0x1c, 0x3d, 0xcc, 0x6e, 0xc4, 0x98, 0x0d, 0x12, 0xab, 0x7d, 0x9d, 0x28, + 0xf9, 0x9d, 0x29, 0xc1, 0x20, 0x75, 0x2c, 0xb2, 0x07, 0x22, 0x4c, 0x16, 0x5a, 0xbd, 0xe7, 0xe0, + 0x33, 0x9f, 0x67, 0xb4, 0xe5, 0x47, 0xe6, 0x3f, 0xa6, 0x0b, 0x61, 0xc7, 0x0b, 0xc0, 0x95, 0x27, + 0x11, 0x66, 0x5f, 0x38, 0x7b, 0x50, 0x00, 0x4c, 0x0b, 0x62, 0x48, 0xd9, 0xba, 0xd5, 0x84, 0x20, + 0xd2, 0xb1, 0xab, 0xbe, 0x7d, 0x17, 0x25, 0xb7, 0x62, 0x46, 0xca, 0x64, 0xcf, 0x45, 0x92, 0xe4, + 0xbf, 0xb8, 0x1f, 0xec, 0x18, 0x33, 0x99, 0xec, 0xf5, 0xcf, 0x6f, 0xae, 0x4c, 0xd5, 0x8e, 0xb7, + 0xb7, 0xd1, 0xb8, 0xac, 0x38, 0xd5, 0xa1, 0x52, 0x7c, 0x9b, 0xbf, 0x95, 0x3d, 0xab, 0xd1, 0xd6, + 0xc1, 0x9d, 0x9d, 0x5c, 0xf3, 0x2c, 0x66, 0xa5, 0xc5, 0xfd, 0xf7, 0xad, 0xc8, 0x1e, 0xde, 0x31, + 0xc1, 0x69, 0x76, 0xd6, 0xfb, 0xb2, 0x3c, 0x8a, 0x07, 0xf1, 0x15, 0x35, 0x1c, 0x7a, 0x3d, 0x53, + 0xd0, 0xd1, 0xee, 0x57, 0x11, 0xc8, 0x05, 0xf7, 0xcd, 0xbc, 0x0f, 0x01, 0x90, 0x80, 0xa3, 0x0a, + 0xd8, 0x3c, 0x13, 0x51, 0x21, 0x94, 0x05, 0x9f, 0xf5, 0x0a, 0xc8, 0xc0, 0xdc, 0xa8, 0x23, 0xb7, + 0xbd, 0xe7, 0xf9, 0x34, 0xb2, 0xe9, 0x1c, 0xb2, 0x19, 0x91, 0x38, 0x5e, 0x21, 0xa6, 0x14, 0x57, + 0x7c, 0xf0, 0x43, 0x60, 0x60, 0xde, 0x54, 0xea, 0x99, 0x95, 0x3c, 0xfa, 0x68, 0x56, 0x0d, 0xff, + 0xb7, 0x17, 0xc5, 0xe2, 0xa2, 0x7e, 0xd8, 0xa7, 0x47, 0x9f, 0xc1, 0xa4, 0xea, 0x47, 0x88, 0x94, + 0xc4, 0xd4, 0x11, 0x37, 0x29, 0xbd, 0xaf, 0x76, 0x9b, 0x3d, 0x6d, 0x09, 0xa3, 0xdf, 0xdf, 0xea, + 0xa0, 0x9e, 0x33, 0xac, 0xf2, 0x30, 0x9c, 0x6a, 0xf7, 0xd5, 0x4e, 0xd8, 0xf4, 0xba, 0xef, 0xea, + 0xf0, 0x8c, 0x3a, 0xa8, 0x3d, 0xb0, 0xf2, 0xc0, 0x7d, 0xef, 0xe2, 0x19, 0xf4, 0x83, 0xbe, 0x10, + 0xdc, 0xdc, 0x14, 0xab, 0xe7, 0x88, 0x8d, 0x7f, 0x5c, 0x73, 0x67, 0x62, 0x54, 0x2e, 0x60, 0x41, + 0x71, 0xf1, 0xf0, 0x6d, 0x03, 0x4e, 0x8f, 0x88, 0x00, 0x1f, 0xe4, 0x62, 0xf1, 0xf3, 0x9e, 0x6c, + 0x3e, 0x39, 0xd2, 0x46, 0x2e, 0xf8, 0xe9, 0x56, 0x26, 0x74, 0x78, 0x0b, 0xd7, 0xb6, 0xb8, 0x5c, + 0xc5, 0xc9, 0xe2, 0x2c, 0x22, 0x35, 0x26, 0x05, 0xa8, 0x4e, 0x65, 0x9e, 0x30, 0xc4, 0x86, 0x11, + 0xbf, 0xa5, 0x0d, 0x79, 0x51, 0x88, 0x2c, 0xff, 0xfd, 0xcc, 0x58, 0x6e, 0xb0, 0xb3, 0xc9, 0x3e, + 0xdd, 0x9a, 0x7f, 0xe2, 0x2f, 0x6c, 0xec, 0x8f, 0xe2, 0x81, 0x54, 0xb5, 0x52, 0xb6, 0x32, 0x60, + 0xc0, 0xca, 0x0a, 0x9b, 0x1d, 0x77, 0xfe, 0x97, 0xb8, 0x58, 0x9d, 0xc9, 0x73, 0xf7, 0xd2, 0x5c, + 0xbe, 0xf9, 0xe6, 0x0c, 0xb4, 0x94, 0x67, 0xdc, 0x1b, 0xf6, 0x23, 0x7e, 0x29, 0x3e, 0x98, 0x0b, + 0x41, 0xc7, 0xb7, 0x0c, 0x7a, 0xee, 0x9b, 0x1d, 0x60, 0xc0, 0x71, 0x0d, 0x45, 0x1f, 0xc9, 0x7f, + 0x04, 0xc8, 0x53, 0x3c, 0x8d, 0x49, 0xa6, 0x54, 0xe3, 0xb8, 0x8e, 0x84, 0x70, 0x54, 0xea, 0xf1, + 0x97, 0xea, 0xeb, 0x01, 0x4b, 0x7e, 0x10, 0xd5, 0xfb, 0x00, 0x34, 0xf4, 0x6e, 0x67, 0x4f, 0xfa, + 0xf6, 0x2e, 0x8c, 0x9e, 0xbd, 0x88, 0xd7, 0xfa, 0x5c, 0x1e, 0x9f, 0xeb, 0xcf, 0xb3, 0xf9, 0xac, 0xf7, 0xec, 0xf9, 0x09, 0xc0, 0xcf, 0x9f, 0x71, 0x0e, 0xd8, 0x84, 0x98, 0x8b, 0xe2, 0x65, 0x51, - 0x64, 0xf1, 0xf5, 0x6d, 0x01, 0x99, 0xf3, 0xd6, 0x38, 0x42, 0x65, 0x4f, 0x11, 0xa8, 0x3f, 0x3b, - 0x38, 0x68, 0x07, 0x2b, 0x44, 0x33, 0xf9, 0x6b, 0x06, 0x14, 0x28, 0xea, 0x6e, 0x55, 0x3a, 0x82, + 0x64, 0xf1, 0xf5, 0x6d, 0x01, 0x99, 0xf3, 0xd6, 0x38, 0x42, 0x65, 0x4f, 0x11, 0xa8, 0xbf, 0x6c, + 0x38, 0x68, 0x07, 0x2b, 0x44, 0x33, 0xf9, 0x83, 0x09, 0x14, 0x28, 0xea, 0x6e, 0x55, 0x3a, 0x82, 0x1f, 0x79, 0x59, 0x1a, 0xbe, 0xa2, 0x90, 0xa1, 0x3a, 0x3f, 0xea, 0x29, 0x16, 0xf1, 0x1d, 0xf4, 0x2c, 0x6f, 0x0d, 0x01, 0x9f, 0x69, 0xf6, 0x24, 0x35, 0x7c, 0x9c, 0xf9, 0x39, 0xb8, 0x96, 0xb7, 0x59, 0x3d, 0x2f, 0x36, 0xb2, 0x15, 0x37, 0x31, 0xeb, 0x3a, 0x7b, 0xdc, 0x33, 0xad, 0x3c, 0x34, 0x89, 0x0e, 0xa4, 0xa6, 0x4f, 0x45, 0xf7, 0x9a, 0xce, 0xa7, 0xc0, 0xa8, 0x4d, 0xe3, 0x63, 0xf0, 0x9b, 0xa3, 0xe0, 0xe9, 0x18, 0x1f, 0x06, 0xd8, 0xb4, 0x07, 0x90, 0xe5, 0x2d, 0x68, 0x1b, 0x66, - 0xb4, 0xfe, 0x94, 0x04, 0x7c, 0xae, 0x57, 0xe6, 0x72, 0xa8, 0xf8, 0xe8, 0x50, 0x11, 0xc6, 0x51, - 0x59, 0x54, 0xdc, 0xc5, 0x3e, 0xfa, 0x68, 0x01, 0xcc, 0x61, 0xde, 0xb5, 0x1b, 0xe8, 0x2f, 0x16, + 0xb4, 0xfe, 0x5a, 0x05, 0x7c, 0xae, 0x57, 0xe6, 0x72, 0xa8, 0xf8, 0xe8, 0x50, 0x11, 0xc6, 0x51, + 0x59, 0x54, 0xdc, 0xc5, 0x3e, 0xfa, 0x2e, 0x02, 0xcc, 0x61, 0xde, 0xb5, 0x1b, 0xe8, 0x8f, 0x22, 0x0e, 0xb9, 0x1c, 0xb7, 0x31, 0x97, 0xc7, 0xee, 0x7b, 0x54, 0x53, 0xe7, 0x4b, 0x7c, 0xc2, 0x93, - 0xf3, 0xe9, 0xbb, 0xb7, 0xc8, 0x99, 0x98, 0xbe, 0xf2, 0x13, 0x8b, 0x26, 0x7d, 0x70, 0xf3, 0x9b, + 0xf3, 0xe9, 0xbb, 0xb7, 0xc8, 0x99, 0x98, 0xbe, 0xf2, 0x2b, 0x8e, 0x26, 0x7d, 0x70, 0xf3, 0x9b, 0x66, 0xc4, 0xaa, 0x19, 0x8b, 0x90, 0x6a, 0x03, 0xf6, 0x4f, 0x9b, 0xbe, 0xe1, 0x17, 0xe7, 0x43, 0xc3, 0x80, 0xf9, 0x8c, 0x91, 0xe4, 0xde, 0x3f, 0xfe, 0x01, 0x5f, 0xb2, 0xab, 0x4a, 0xdc, 0xde, 0xa4, 0xf7, 0x93, 0x34, 0x88, 0x9e, 0x69, 0xdb, 0xb6, 0xd8, 0x9b, 0x35, 0x1b, 0x54, 0x60, 0x81, @@ -423,9 +424,9 @@ const char SETUP_HTML[] PROGMEM = { 0x76, 0x5c, 0x5f, 0xf8, 0x13, 0x88, 0xba, 0xce, 0xd4, 0xf0, 0xb5, 0xc1, 0x85, 0xf5, 0x59, 0xdf, 0xbc, 0x4b, 0xe3, 0x45, 0x95, 0x93, 0xd3, 0x19, 0x96, 0x96, 0xcc, 0xf6, 0x9d, 0xe3, 0xff, 0x3d, 0xba, 0x8b, 0xe4, 0x59, 0x0d, 0x8d, 0x46, 0x7a, 0x1c, 0x0d, 0xd5, 0x4e, 0xe3, 0x91, 0xfe, 0x13, - 0x78, 0xa4, 0x47, 0xf0, 0xa0, 0xdf, 0x14, 0x02, 0x06, 0x74, 0xab, 0x60, 0x9d, 0x15, 0xa7, 0x9d, + 0x78, 0xa4, 0x47, 0xf0, 0xa0, 0x9f, 0x2d, 0x02, 0x06, 0x74, 0xab, 0x60, 0x9d, 0x15, 0xa7, 0x9d, 0x4f, 0xdb, 0xbd, 0xb1, 0xf1, 0x64, 0xe9, 0x7d, 0xef, 0xf9, 0x46, 0x86, 0x0b, 0xb0, 0xcd, 0x96, - 0x87, 0x4e, 0x7a, 0xf4, 0x01, 0x19, 0x05, 0xe4, 0x0a, 0x65, 0x1a, 0xab, 0x65, 0xd6, 0x85, 0x12, + 0x87, 0x4e, 0x7a, 0xf4, 0x8d, 0x1a, 0x05, 0xe4, 0x0a, 0x65, 0x1a, 0xab, 0x65, 0xd6, 0x85, 0x12, 0x15, 0x02, 0x06, 0x3c, 0x45, 0x64, 0x1e, 0x17, 0x09, 0x9f, 0x05, 0x04, 0x2b, 0x40, 0xcc, 0x09, 0x2c, 0x39, 0xf7, 0xe9, 0xc6, 0x53, 0x30, 0x86, 0x5d, 0xde, 0x99, 0x67, 0x22, 0x98, 0xad, 0x5c, 0xa7, 0x29, 0xa6, 0x39, 0x1b, 0x4c, 0x56, 0xa8, 0x22, 0x5d, 0x1a, 0x1b, 0x0e, 0xa5, 0x5d, 0x5d, @@ -433,15 +434,15 @@ const char SETUP_HTML[] PROGMEM = { 0x53, 0xc9, 0xee, 0xe6, 0xd0, 0x71, 0xd4, 0x0e, 0xfb, 0x13, 0x3e, 0xf2, 0x90, 0x64, 0x7f, 0x4a, 0x5c, 0x39, 0xee, 0x9e, 0x65, 0x38, 0x38, 0xf0, 0xcf, 0x8d, 0x73, 0xbd, 0x0a, 0xc8, 0x09, 0x15, 0xdb, 0x82, 0x60, 0xcc, 0x07, 0x8f, 0x40, 0x51, 0x5c, 0x37, 0x53, 0x9b, 0x98, 0x74, 0xa9, 0x7e, - 0x96, 0x52, 0x90, 0x4b, 0x6b, 0x48, 0xb1, 0x55, 0x10, 0xb5, 0x0b, 0xd2, 0xb6, 0x3f, 0xa7, 0xcc, + 0xf9, 0x52, 0x90, 0x4b, 0x6b, 0x48, 0xb1, 0x55, 0x10, 0xb5, 0x0b, 0xd2, 0xb6, 0x3f, 0xa7, 0xcc, 0x75, 0xb1, 0xf8, 0x81, 0xe8, 0x2e, 0x9d, 0x62, 0xd1, 0xdf, 0x6b, 0xbb, 0x2d, 0xd4, 0x2c, 0x60, 0x73, 0xc8, 0xde, 0x3a, 0x53, 0xdb, 0xbe, 0x9a, 0xd1, 0xb5, 0xe0, 0x9d, 0x58, 0xdc, 0x27, 0xd9, 0x4c, 0xd5, 0x4d, 0x9a, 0x74, 0x94, 0xae, 0xc4, 0xff, 0xcd, 0x37, 0x47, 0xc4, 0xaf, 0xe3, 0x39, 0x44, 0xcc, 0xbe, 0xb1, 0xae, 0x32, 0xc0, 0x7e, 0x23, 0xb1, 0xcf, 0xfb, 0x27, 0x34, 0x55, 0x25, 0xe3, 0xc7, 0x54, 0x55, 0x83, 0xa8, 0x5c, 0xad, 0x50, 0x33, 0x89, 0xe3, 0xf9, 0x81, 0x74, 0xd9, 0x9c, 0x22, 0x34, 0x29, 0xcb, 0x15, 0x37, 0x45, 0x2b, 0x3f, 0xce, 0x39, 0xf9, 0x2a, 0x79, 0x6d, - 0x4b, 0x9c, 0xc4, 0xe2, 0x88, 0x91, 0xd2, 0xe8, 0x8b, 0xd9, 0x9b, 0xa8, 0x58, 0xd9, 0xfc, 0xd9, - 0xae, 0xa6, 0xf3, 0x3f, 0xce, 0xdc, 0x73, 0x74, 0x2e, 0xc4, 0xb6, 0xdf, 0x3f, 0xaf, 0x9e, 0xa7, + 0x4b, 0x9c, 0xc4, 0xe2, 0x88, 0x91, 0xd2, 0xe8, 0x8b, 0xd9, 0x9b, 0xa8, 0x58, 0xd9, 0xfc, 0x65, + 0xb0, 0xa6, 0xf3, 0x3f, 0xce, 0xdc, 0x73, 0x74, 0x2e, 0xc4, 0xb6, 0xdf, 0x3f, 0xaf, 0x9e, 0xa7, 0x8f, 0x31, 0xaf, 0x5d, 0x4f, 0xbd, 0x7a, 0xa6, 0xea, 0x7d, 0x50, 0xbb, 0x8e, 0x37, 0x54, 0x89, 0x5b, 0x47, 0x5d, 0xf4, 0x89, 0xeb, 0xa2, 0x4f, 0x15, 0x39, 0x3f, 0xf2, 0x30, 0x67, 0x98, 0x65, 0x16, 0xe9, 0xf7, 0xf1, 0x27, 0xb1, 0x38, 0xf3, 0xfb, 0xfb, 0x0e, 0x9d, 0xe3, 0xd4, 0x21, 0x7b, @@ -455,13 +456,13 @@ const char SETUP_HTML[] PROGMEM = { 0x9b, 0x43, 0x3d, 0x54, 0xc1, 0xb9, 0x98, 0xed, 0xf6, 0x53, 0xad, 0x52, 0x35, 0xd5, 0x17, 0x95, 0xea, 0x8b, 0x9a, 0xea, 0x8b, 0x4a, 0x79, 0x71, 0x9f, 0x75, 0x43, 0x46, 0x2d, 0xb4, 0xf8, 0xa0, 0x92, 0x14, 0x9c, 0xeb, 0xa2, 0x4f, 0x87, 0x75, 0x11, 0x85, 0x9a, 0x26, 0x99, 0x05, 0x7b, 0x4b, - 0xa3, 0x59, 0xb8, 0xa5, 0x5f, 0x1d, 0xfe, 0x01, 0x8a, 0xab, 0x10, 0x6c, 0x2d, 0xe4, 0x44, 0x77, + 0xa3, 0x59, 0xb8, 0xa5, 0x1f, 0x36, 0xfe, 0x01, 0x8a, 0xab, 0x10, 0x6c, 0x2d, 0xe4, 0x44, 0x77, 0xa2, 0x31, 0xb3, 0xad, 0x26, 0xad, 0x7f, 0x4c, 0xd2, 0xeb, 0xb3, 0x5f, 0xfe, 0xcf, 0xbb, 0x9f, 0x7e, 0xa4, 0xe9, 0x3a, 0x12, 0xfc, 0x78, 0xf9, 0xa0, 0x27, 0x62, 0xe6, 0xe6, 0x36, 0x49, 0x4c, 0xaf, 0xff, 0xc1, 0xdc, 0x91, 0x7e, 0x4c, 0x7a, 0x50, 0x66, 0xe4, 0xaf, 0x3c, 0x9f, 0x3d, 0xa7, 0x39, 0x6a, 0x6f, 0x0f, 0xc4, 0x19, 0xcc, 0xf7, 0x48, 0xde, 0xbf, 0x43, 0xc6, 0x3c, 0xd5, 0x9e, - 0x46, 0x26, 0xd0, 0xf0, 0x69, 0x66, 0xaf, 0x3e, 0xe1, 0x05, 0x35, 0x72, 0xc2, 0xdb, 0xe3, 0xef, - 0x72, 0x7b, 0xe6, 0x0e, 0x38, 0xad, 0xd2, 0xc5, 0xa4, 0xf7, 0xf6, 0xa7, 0x77, 0x3f, 0xf7, 0x4c, + 0x46, 0x26, 0xd0, 0xf0, 0x69, 0x66, 0xaf, 0x3e, 0xe1, 0x05, 0x35, 0x72, 0xc2, 0xdb, 0xe3, 0x4f, + 0x7f, 0x7b, 0xe6, 0x0e, 0x38, 0xad, 0xd2, 0xc5, 0xa4, 0xf7, 0xf6, 0xa7, 0x77, 0x3f, 0xf7, 0x4c, 0xca, 0x63, 0x26, 0xc5, 0xbe, 0x31, 0x1b, 0x26, 0x7d, 0x6e, 0xcd, 0x86, 0x0f, 0xd7, 0x31, 0xf9, 0xe8, 0x7a, 0xaa, 0x73, 0xd9, 0xde, 0x3b, 0x51, 0x14, 0x20, 0x26, 0x67, 0xd2, 0x17, 0x46, 0x7e, 0x3b, 0x9f, 0xa3, 0xe5, 0x12, 0xf4, 0x3c, 0x18, 0x60, 0xc8, 0x12, 0xc6, 0xb6, 0x32, 0xd6, 0x98, @@ -469,33 +470,33 @@ const char SETUP_HTML[] PROGMEM = { 0xc7, 0xf0, 0x40, 0x07, 0x5b, 0x2e, 0x72, 0xe9, 0xd7, 0x8a, 0xe9, 0x8b, 0x54, 0x6d, 0xc4, 0xd3, 0xec, 0xbc, 0xce, 0xf2, 0x92, 0x57, 0xa2, 0xe4, 0x15, 0x2f, 0x81, 0x99, 0xad, 0xb5, 0xb0, 0xbe, 0x59, 0x35, 0x68, 0x2c, 0x66, 0xd6, 0xd6, 0xb5, 0x0e, 0x1b, 0x96, 0x1f, 0x0c, 0xc9, 0xa6, 0xd5, - 0x6b, 0xb9, 0xec, 0x26, 0x5d, 0x1f, 0x34, 0xbc, 0x83, 0xf5, 0xc2, 0xcc, 0x84, 0xfc, 0xc1, 0x89, + 0x6b, 0xb9, 0xec, 0x26, 0x5d, 0x1f, 0x34, 0xbc, 0x83, 0xf5, 0xc2, 0xcc, 0x84, 0xfc, 0x4d, 0x8b, 0x09, 0x26, 0x64, 0x49, 0x82, 0x1c, 0x6f, 0x3f, 0x7d, 0xca, 0x3a, 0x48, 0xc9, 0x37, 0xf5, 0xb9, 0x0b, 0x52, 0x40, 0xcd, 0xa8, 0x8e, 0x35, 0x6d, 0x5a, 0x25, 0xb9, 0x4c, 0x17, 0x08, 0x4d, 0x94, 0xa0, 0x16, 0xb7, 0xb9, 0xa9, 0xd9, 0xbb, 0xef, 0x77, 0x75, 0xf3, 0x1c, 0x67, 0x36, 0x9b, 0xe9, - 0x5e, 0xdf, 0x1e, 0x8a, 0x5f, 0xb1, 0x5a, 0x50, 0x62, 0x4a, 0x1f, 0xd4, 0xff, 0xfc, 0xc3, 0x7f, + 0x5e, 0xdf, 0x1e, 0x8a, 0x5f, 0xb1, 0x5a, 0x50, 0x62, 0x4a, 0xdf, 0xec, 0xff, 0xfc, 0xc3, 0x7f, 0x1a, 0xf7, 0x71, 0x92, 0xe8, 0xc5, 0x6c, 0x63, 0x93, 0xde, 0xf3, 0xb7, 0xb0, 0xc6, 0x7f, 0xd1, 0xc7, 0x6e, 0x24, 0x86, 0x1f, 0xde, 0x1a, 0x71, 0x6e, 0xd0, 0x8c, 0x6e, 0x72, 0x08, 0xef, 0x55, 0x96, 0xa5, 0x59, 0xb9, 0x28, 0x4e, 0x2f, 0xa4, 0x36, 0xf3, 0x52, 0xa0, 0x13, 0x00, 0xbb, 0x40, 0x5f, 0x5a, 0x81, 0xba, 0xbe, 0xa8, 0x34, 0xe8, 0xd7, 0xae, 0xb0, 0x96, 0xf3, 0x40, 0xa2, 0x12, - 0x3e, 0xe9, 0x2b, 0x4a, 0xc1, 0xf8, 0x9b, 0xfc, 0x4e, 0x5e, 0x57, 0xbf, 0x52, 0x81, 0xa1, 0xba, - 0x97, 0x29, 0x5f, 0x26, 0x09, 0x4f, 0x7c, 0x9b, 0x19, 0x84, 0xe8, 0x00, 0xa6, 0xbe, 0xcd, 0x67, + 0x3e, 0xe9, 0x2b, 0x4a, 0xc1, 0xf8, 0xb3, 0xff, 0x4e, 0x5e, 0x57, 0x3f, 0x84, 0x81, 0xa1, 0xba, + 0x97, 0x29, 0x5f, 0x26, 0x09, 0x4f, 0x7c, 0x9b, 0x19, 0x84, 0xe8, 0x00, 0xa6, 0x3e, 0xff, 0x67, 0xad, 0x2f, 0x5d, 0x77, 0x7b, 0x6a, 0xab, 0xda, 0x9c, 0x1a, 0xcc, 0xd6, 0xeb, 0x0b, 0x27, 0xc6, - 0x6c, 0x2d, 0xfc, 0xd4, 0xd6, 0x83, 0x6f, 0xba, 0x67, 0xdd, 0xfd, 0x13, 0xaa, 0xd6, 0xd3, 0x3f, - 0x36, 0x80, 0xd8, 0x55, 0x5f, 0x57, 0x56, 0x9e, 0xbb, 0x15, 0xd2, 0xbf, 0x53, 0xaf, 0xdf, 0x67, + 0x6c, 0x2d, 0xfc, 0xd4, 0xd6, 0x83, 0x6f, 0xba, 0x67, 0xdd, 0xfd, 0x13, 0xaa, 0xd6, 0xd3, 0xbf, + 0x67, 0x80, 0xd8, 0x55, 0x5f, 0x57, 0x56, 0x9e, 0xbb, 0x15, 0xd2, 0xbf, 0x53, 0xaf, 0xdf, 0x67, 0xd1, 0x0d, 0xc7, 0xf6, 0xfe, 0xb4, 0x99, 0x0e, 0x81, 0xe7, 0xea, 0xc3, 0xa6, 0xde, 0x53, 0x51, 0x6b, 0x85, 0xf9, 0x3a, 0x84, 0xe3, 0xeb, 0x8c, 0xec, 0xb6, 0x8f, 0x34, 0xad, 0xf3, 0xa7, 0xb1, 0xa9, 0x43, 0xc7, 0x6f, 0xe5, 0x52, 0x64, 0x97, 0x5e, 0x70, 0xb7, 0xba, 0x52, 0xec, 0x89, 0x05, - 0xfc, 0xf5, 0xc1, 0x65, 0x94, 0x24, 0xf4, 0x53, 0x2b, 0xd5, 0x96, 0x52, 0x7f, 0x57, 0xdb, 0x30, + 0xfc, 0xf5, 0xc1, 0x65, 0x94, 0x24, 0xf4, 0x6b, 0x2e, 0xd5, 0x96, 0x52, 0x7f, 0x57, 0xdb, 0x30, 0x3a, 0x50, 0x79, 0x24, 0x89, 0x66, 0xce, 0x03, 0x35, 0xbe, 0x03, 0x69, 0x2e, 0xf3, 0x99, 0xb5, 0x6a, 0xf2, 0x17, 0xcd, 0x95, 0x78, 0xae, 0xad, 0x7f, 0xaf, 0x83, 0x6a, 0x1a, 0x67, 0xf6, 0x85, - 0xd3, 0x5a, 0xc5, 0x91, 0x33, 0x46, 0xf9, 0x63, 0x72, 0xb4, 0x21, 0x76, 0x9b, 0x9d, 0xf9, 0xdb, + 0xd3, 0x5a, 0xc5, 0x91, 0x33, 0x46, 0xf9, 0x7b, 0x75, 0xb4, 0x21, 0x76, 0x9b, 0x9d, 0xf9, 0xdb, 0x4f, 0xfd, 0x9e, 0x9c, 0xd5, 0x3a, 0x48, 0x49, 0xf2, 0x6f, 0xcf, 0x9a, 0x64, 0xe4, 0x04, 0x42, 0x7f, 0xdc, 0x71, 0x82, 0xcd, 0xfd, 0xc9, 0xb1, 0x76, 0x9d, 0x3c, 0x3e, 0xfc, 0x52, 0x43, 0x48, 0x26, 0x74, 0xd2, 0xe1, 0x9e, 0xa4, 0xa3, 0x86, 0x7e, 0x03, 0xf7, 0x6f, 0xbe, 0x11, 0xdf, 0x7c, 0xd3, 0x28, 0xa9, 0xef, 0x44, 0x28, 0x0f, 0xf5, 0xea, 0xdd, 0xdb, 0x46, 0x94, 0x78, 0xea, 0x6a, 0xb2, 0xea, 0x7e, 0x64, 0x25, 0xb9, 0x23, 0x66, 0x75, 0x7c, 0xf0, 0x64, 0xfe, 0xaf, 0xec, 0x0b, - 0x36, 0x3c, 0x9f, 0xfc, 0x75, 0x15, 0x5a, 0xc5, 0xad, 0x6f, 0x55, 0xd6, 0x57, 0x54, 0xe9, 0x96, + 0x36, 0x3c, 0x9f, 0xfc, 0x01, 0x17, 0x5a, 0xc5, 0xad, 0x6f, 0x55, 0xd6, 0x57, 0x54, 0xe9, 0x96, 0xff, 0xe2, 0x7c, 0xd0, 0x19, 0x06, 0x5e, 0xff, 0xc4, 0xbf, 0xf3, 0x00, 0xf3, 0x4d, 0x37, 0xd4, 0x7b, 0x16, 0xe5, 0x0f, 0x9b, 0x39, 0xa7, 0x73, 0x7a, 0xeb, 0xe6, 0x48, 0x2e, 0x12, 0xaf, 0x49, 0x8a, 0x98, 0x60, 0x4d, 0x69, 0x17, 0x2b, 0x62, 0xbc, 0x9f, 0x94, 0x87, 0x4c, 0xcb, 0xdd, 0x59, @@ -506,24 +507,24 @@ const char SETUP_HTML[] PROGMEM = { 0xf3, 0x76, 0x03, 0x3e, 0xe8, 0xa1, 0x9b, 0xd0, 0x56, 0x62, 0xbb, 0x01, 0x1d, 0x75, 0xd5, 0xf5, 0x3a, 0x8a, 0xb7, 0x9a, 0xa8, 0x30, 0x5b, 0x42, 0x91, 0x39, 0x52, 0x13, 0x0a, 0xca, 0x74, 0xbd, 0xd2, 0x98, 0x76, 0x13, 0xa5, 0x5b, 0xd4, 0xaa, 0xf6, 0x21, 0xd5, 0xc1, 0x58, 0xa5, 0x9e, 0x1e, - 0x5d, 0xe4, 0x57, 0xfb, 0x00, 0x4f, 0x5a, 0xb2, 0x3f, 0xfd, 0xbb, 0x3e, 0x6a, 0xeb, 0x57, 0xfe, + 0x5d, 0xe4, 0x57, 0xfb, 0x00, 0x4f, 0x5a, 0xb2, 0x3f, 0xfd, 0xd3, 0x41, 0x6a, 0xeb, 0x57, 0xfe, 0x5e, 0x0a, 0x2d, 0xc3, 0x1e, 0x5d, 0xb9, 0x55, 0x3e, 0x99, 0xdb, 0x97, 0x5f, 0x41, 0x9f, 0xea, 0x51, 0xdb, 0x1a, 0xe6, 0x4e, 0xf5, 0x2f, 0x8b, 0x4f, 0xf5, 0xab, 0xe7, 0x8f, 0x72, 0xb4, 0xea, 0x8b, 0xd1, 0x93, 0x18, 0x36, 0x54, 0xb0, 0x5f, 0xee, 0x7e, 0x37, 0x7e, 0x01, 0xe2, 0x31, 0x12, - 0xeb, 0x67, 0x09, 0x24, 0x08, 0xf1, 0x38, 0xc6, 0xad, 0x55, 0x6d, 0xfe, 0x05, 0x9c, 0x5f, 0xd1, + 0xeb, 0x67, 0x09, 0x24, 0x08, 0xf1, 0x38, 0xc6, 0xad, 0x55, 0x6d, 0xfe, 0xd1, 0x9b, 0x5f, 0xd1, 0xbe, 0xd2, 0x96, 0xa3, 0x3d, 0x2a, 0x5f, 0xd9, 0x37, 0x95, 0x4b, 0x3c, 0x6c, 0x4b, 0xe2, 0x65, 0xb6, 0xb7, 0xb8, 0xd0, 0x62, 0xfc, 0x22, 0xce, 0x69, 0x67, 0x70, 0xa1, 0xa2, 0xd3, 0x49, 0xce, 0xc8, 0x85, 0x27, 0x39, 0x07, 0xa6, 0x4c, 0xb4, 0x23, 0x09, 0xb7, 0x13, 0xde, 0xeb, 0xfc, 0xf6, 0xe4, 0x40, 0x93, 0x53, 0xb5, 0x2e, 0x1c, 0xe4, 0xf4, 0xc5, 0xb9, 0xfa, 0xa2, 0xaf, 0xf9, 0x7d, 0x5f, 0xf5, 0x35, 0x60, 0x99, 0xdd, 0x1c, 0x60, 0xf9, 0xec, 0xbb, 0x9f, 0xde, 0xa8, 0xc5, 0x1f, 0xfa, 0xae, 0x56, 0x2c, 0x9e, 0x99, 0xc6, 0x59, 0xdf, 0x98, 0x5d, 0x18, 0xbb, 0xe6, 0x07, 0x86, - 0xd2, 0x59, 0xaa, 0x5f, 0x93, 0x52, 0x2b, 0x1e, 0xc6, 0xec, 0xe8, 0x41, 0x93, 0x67, 0xaa, 0xe5, + 0xd2, 0x59, 0xaa, 0x1f, 0xac, 0x52, 0x2b, 0x1e, 0xc6, 0xec, 0xe8, 0x41, 0x93, 0x67, 0xaa, 0xe5, 0xb3, 0xfe, 0xb4, 0x09, 0x47, 0x7a, 0xd0, 0x67, 0xe7, 0x65, 0xfd, 0xe1, 0xe7, 0x92, 0x32, 0xee, - 0xa8, 0x0c, 0x45, 0x10, 0x2e, 0xfa, 0x59, 0x87, 0xa6, 0x63, 0x7d, 0xf4, 0x8f, 0x5d, 0x1d, 0xa2, + 0xa8, 0x0c, 0x45, 0x10, 0x2e, 0xfa, 0x59, 0x87, 0xa6, 0x63, 0x7d, 0xf4, 0xef, 0x69, 0x1d, 0xa2, 0xaf, 0xff, 0x6b, 0x12, 0x50, 0x5f, 0xfb, 0x02, 0x31, 0xaa, 0x72, 0x7a, 0xd8, 0x75, 0xdf, 0x35, 0xa4, 0x72, 0xd3, 0x9c, 0xe8, 0x1f, 0x1f, 0xb1, 0xe9, 0xc3, 0x9f, 0x7d, 0x2f, 0x56, 0x89, 0xc8, 0x8c, 0x6b, 0x11, 0xaf, 0x8d, 0x97, 0xd7, 0xd9, 0xed, 0x12, 0xb1, 0x8f, 0xbe, 0x72, 0x7e, 0x2f, 0xc7, 0x9e, 0x80, 0xff, 0xdc, 0xb2, 0xcd, 0x37, 0x89, 0x45, 0xad, 0xb0, 0x7c, 0xa9, 0x49, 0x1f, - 0xf3, 0x0a, 0xf9, 0x5b, 0x3f, 0xfc, 0xa3, 0x6b, 0xf4, 0x3f, 0x1c, 0xfa, 0x1f, 0xb9, 0x8d, 0x92, - 0xce, 0x88, 0x68, 0x00, 0x00 + 0xf3, 0x0a, 0xf9, 0x5b, 0x3f, 0xfc, 0xbb, 0x6e, 0xf4, 0xff, 0x34, 0xfa, 0x1f, 0xf1, 0x7f, 0x3c, + 0x01, 0xeb, 0x68, 0x00, 0x00 }; \ No newline at end of file diff --git a/lib/webserver/src/setup.htm b/lib/webserver/src/setup.htm deleted file mode 100644 index 271fe92e..00000000 --- a/lib/webserver/src/setup.htm +++ /dev/null @@ -1,110 +0,0 @@ - - - - - SmartPusher - - - - -
-
-
- -

SmartPusher

-
-
- - WiFi Setup - - - About - -
- -
-
-
-
-
-

Connect to WiFi

-
- - -
-
-
-
-
-
- - -
-
- - - -
-
-
-
- - -
- Scan WiFi networks -
- -
- Connect to SSID -
-
-
- -
-
Loading...
- - - - \ No newline at end of file diff --git a/lib/webserver/src/setup_htm.h b/lib/webserver/src/setup_htm.h deleted file mode 100644 index 43ff83ba..00000000 --- a/lib/webserver/src/setup_htm.h +++ /dev/null @@ -1,529 +0,0 @@ -#define SETUP_HTML_SIZE 8405 -const char SETUP_HTML[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xed, 0x7d, 0xe9, 0x77, 0xdb, 0x46, - 0x96, 0xef, 0xf7, 0x39, 0x67, 0xfe, 0x07, 0x84, 0x59, 0x2c, 0x8e, 0x01, 0x08, 0x0b, 0x09, 0x70, - 0x31, 0x95, 0x76, 0x2b, 0xce, 0x71, 0xde, 0x93, 0x13, 0x9f, 0x76, 0xda, 0x3d, 0xd3, 0x39, 0x3e, - 0xaf, 0x21, 0xb2, 0x28, 0xa2, 0x0d, 0x12, 0x1c, 0x00, 0x92, 0x2c, 0xb3, 0xf9, 0xbf, 0xcf, 0xef, - 0xde, 0xaa, 0xc2, 0x46, 0x90, 0x52, 0xba, 0x93, 0xf9, 0xf4, 0x62, 0x1b, 0x4b, 0x2d, 0xb7, 0xee, - 0x7e, 0x6f, 0x2d, 0x60, 0x5e, 0x7c, 0xf1, 0xdd, 0x4f, 0x97, 0x3f, 0xff, 0xd7, 0xdb, 0x57, 0xc6, - 0xaa, 0x58, 0x27, 0x17, 0xff, 0xfe, 0x6f, 0x2f, 0xd4, 0x9d, 0x9e, 0x44, 0xb4, 0xc0, 0x93, 0x81, - 0xff, 0x5e, 0xac, 0x45, 0x11, 0x19, 0xf3, 0x55, 0x94, 0xe5, 0xa2, 0x98, 0xdd, 0x16, 0x4b, 0x6b, - 0x64, 0x9c, 0xeb, 0xba, 0x22, 0x2e, 0x12, 0x71, 0xf1, 0xf2, 0x2f, 0x3f, 0xff, 0xe9, 0x87, 0xff, - 0x34, 0xae, 0xe2, 0x9b, 0x55, 0xf1, 0xe2, 0x5c, 0x96, 0x35, 0x3a, 0xa7, 0x9b, 0x42, 0x6c, 0x8a, - 0x59, 0xef, 0x3e, 0x5e, 0x14, 0xab, 0xd9, 0x42, 0xdc, 0xc5, 0x73, 0x61, 0xf1, 0x8b, 0x69, 0xc4, - 0x9b, 0xb8, 0x88, 0xa3, 0xc4, 0xca, 0xe7, 0x51, 0x22, 0x66, 0x6e, 0xcf, 0xd8, 0x44, 0x6b, 0x31, - 0xbb, 0x8b, 0xc5, 0xfd, 0x36, 0xcd, 0x8a, 0x6a, 0xa8, 0xbc, 0x78, 0x00, 0x58, 0x3b, 0xde, 0x6c, - 0x81, 0x43, 0x9c, 0x88, 0xdd, 0x4a, 0xd0, 0x78, 0x13, 0xd7, 0xd9, 0x7e, 0x9a, 0xa6, 0xdb, 0x68, - 0x1e, 0x17, 0x0f, 0x13, 0x67, 0x9a, 0xde, 0x89, 0x6c, 0x99, 0xa4, 0xf7, 0x93, 0x55, 0xbc, 0x58, - 0x88, 0xcd, 0x74, 0x9b, 0xe6, 0x80, 0x9f, 0x6e, 0x26, 0xd1, 0x75, 0x9e, 0x26, 0xb7, 0x85, 0x98, - 0xf2, 0xb8, 0xb2, 0xdb, 0x67, 0x2b, 0xde, 0x2c, 0xc4, 0xa7, 0x89, 0xe5, 0xee, 0xed, 0x24, 0x8d, - 0x16, 0x22, 0x33, 0xd5, 0x7d, 0x12, 0x2d, 0x8b, 0xda, 0xdb, 0xb5, 0x58, 0xa6, 0x99, 0xd8, 0x59, - 0xf7, 0xe2, 0xfa, 0x63, 0x5c, 0x58, 0xd1, 0x26, 0x5e, 0x47, 0x04, 0xd5, 0x02, 0x26, 0x89, 0xb5, - 0x4e, 0x17, 0x62, 0x72, 0x9d, 0x16, 0xab, 0xe9, 0xd1, 0x8a, 0x83, 0x9e, 0x13, 0x82, 0x1c, 0x1a, - 0xae, 0x3d, 0xca, 0x0d, 0x11, 0xe5, 0x02, 0x98, 0x58, 0xe9, 0x6d, 0x01, 0x76, 0x2c, 0x89, 0x23, - 0x62, 0xfa, 0xf4, 0x96, 0xd7, 0x69, 0x06, 0x1c, 0xad, 0x2c, 0x5a, 0xc4, 0xb7, 0xf9, 0x64, 0xe8, - 0x7c, 0x3d, 0x55, 0xac, 0xf1, 0xc4, 0x5a, 0x51, 0x8b, 0x27, 0x4d, 0x61, 0x07, 0x11, 0x0b, 0x91, - 0x44, 0x0f, 0x13, 0xcb, 0x76, 0x83, 0x7c, 0xda, 0x5d, 0x3a, 0x4f, 0x93, 0x34, 0x9b, 0x7c, 0xe9, - 0xfb, 0xfe, 0x74, 0x09, 0x61, 0x5a, 0x79, 0xfc, 0x59, 0x48, 0x16, 0xae, 0xa3, 0xec, 0x06, 0x08, - 0x25, 0x62, 0x59, 0x4c, 0xa2, 0xdb, 0x22, 0xd5, 0x05, 0x19, 0x63, 0xc0, 0x25, 0xa5, 0x08, 0x32, - 0x40, 0x2c, 0xe2, 0x3b, 0x31, 0x2d, 0xc4, 0xa7, 0x82, 0x59, 0xbf, 0x29, 0x26, 0xd6, 0x18, 0xff, - 0x01, 0x51, 0x8d, 0x56, 0x91, 0x45, 0x9b, 0x1c, 0xdc, 0x5e, 0x4f, 0xf8, 0x09, 0x3d, 0xc4, 0x5f, - 0xcf, 0x9c, 0xfe, 0xd4, 0x5a, 0xe7, 0x47, 0xeb, 0x8e, 0x95, 0x6b, 0xf9, 0x62, 0x84, 0xfd, 0x49, - 0xc1, 0x2a, 0x0d, 0x9d, 0xf4, 0x7a, 0x1d, 0x0a, 0x53, 0xa4, 0xdb, 0x89, 0xb3, 0x7f, 0x54, 0x15, - 0x34, 0xbf, 0x7c, 0xaf, 0x8b, 0x8b, 0x54, 0xca, 0x4c, 0xb2, 0x06, 0xf6, 0xb0, 0x92, 0x86, 0x44, - 0x67, 0xc7, 0x35, 0xb2, 0xe2, 0x0f, 0x1a, 0xf2, 0x47, 0xf1, 0xb0, 0xcc, 0x60, 0x0b, 0xb9, 0xc1, - 0x0a, 0xb0, 0x73, 0xbe, 0x36, 0x47, 0xf8, 0x57, 0xa4, 0xbb, 0xeb, 0xf4, 0x93, 0x95, 0xaf, 0xa2, - 0x05, 0xb4, 0xdc, 0x31, 0x3c, 0xea, 0x65, 0x38, 0x86, 0xe5, 0xda, 0x3e, 0xba, 0x0f, 0x9c, 0xaf, - 0xbb, 0xeb, 0x9d, 0xfd, 0xfe, 0x0f, 0xbf, 0x3d, 0xc8, 0x22, 0x9b, 0xac, 0xc8, 0xe4, 0x76, 0xd0, - 0xf7, 0x82, 0xb8, 0xc3, 0x72, 0xdf, 0x88, 0x3c, 0x3f, 0x1b, 0x0d, 0xbf, 0xee, 0xef, 0xed, 0x05, - 0x19, 0x41, 0x94, 0xec, 0xae, 0xa3, 0xf9, 0xc7, 0x9b, 0x2c, 0xbd, 0xdd, 0x2c, 0x2c, 0xa9, 0x4c, - 0x2b, 0x88, 0xe9, 0xcc, 0x31, 0x31, 0xbc, 0xeb, 0xe0, 0x62, 0x8f, 0x87, 0x7d, 0xa5, 0xc9, 0x13, - 0x77, 0xfb, 0xc9, 0x00, 0xef, 0xe3, 0x85, 0x41, 0x1a, 0x87, 0xff, 0x82, 0xb6, 0x92, 0xb3, 0xea, - 0x35, 0x70, 0xf2, 0xd1, 0x67, 0x84, 0x7f, 0xd9, 0xcd, 0x35, 0x83, 0xc5, 0x1f, 0xdb, 0x1b, 0xf4, - 0xa7, 0xcb, 0x44, 0x7c, 0xb2, 0x16, 0x71, 0x26, 0xe6, 0x2c, 0x54, 0x8c, 0x7d, 0xbb, 0xde, 0x48, - 0x49, 0x90, 0xa5, 0xac, 0xa3, 0x4f, 0x96, 0xb2, 0x96, 0x81, 0x73, 0xb7, 0xe2, 0x77, 0x69, 0x32, - 0x63, 0xd4, 0xb2, 0x9e, 0x46, 0x49, 0x7c, 0x03, 0x23, 0x44, 0x0f, 0xd6, 0x84, 0x01, 0x95, 0x1f, - 0xea, 0xdb, 0x99, 0x05, 0x70, 0x26, 0x5d, 0xfa, 0xda, 0xe6, 0xc0, 0xa4, 0xa6, 0x06, 0x2a, 0x5e, - 0x98, 0xfa, 0xc1, 0x9a, 0x27, 0x69, 0x2e, 0x76, 0x8b, 0x38, 0xdf, 0x92, 0x92, 0x10, 0xaa, 0x87, - 0xea, 0xb7, 0x6f, 0xb5, 0x66, 0x74, 0x2c, 0xd8, 0xfd, 0x3a, 0x9f, 0xcc, 0xa1, 0xb3, 0x22, 0xd3, - 0xd6, 0xe9, 0xba, 0xee, 0xc8, 0x0b, 0xa7, 0xf3, 0xdb, 0x2c, 0xc7, 0xeb, 0x36, 0x8d, 0xb9, 0x52, - 0x53, 0x47, 0x32, 0x9b, 0xfe, 0xfd, 0x36, 0x2f, 0xe2, 0xe5, 0x83, 0xa5, 0xf5, 0x5d, 0x01, 0x90, - 0xc6, 0xea, 0x48, 0x4d, 0x57, 0xe8, 0x2b, 0x35, 0xd5, 0x83, 0xb3, 0x57, 0xdf, 0x35, 0x47, 0xda, - 0x46, 0x8b, 0x45, 0xbc, 0xb9, 0x99, 0xb8, 0xac, 0x0f, 0xe4, 0x6d, 0x0e, 0x4d, 0x5d, 0x02, 0x83, - 0x6f, 0x9f, 0x9f, 0x91, 0x9c, 0x0d, 0xcb, 0x60, 0xc0, 0xfd, 0x1a, 0x59, 0x12, 0x97, 0x9d, 0x92, - 0x30, 0xe1, 0x50, 0x53, 0x00, 0xe1, 0xd0, 0x9f, 0xca, 0xad, 0x4b, 0x8f, 0xa2, 0x06, 0x66, 0xb7, - 0x86, 0x0e, 0x9b, 0xe8, 0xee, 0x50, 0xc1, 0xd8, 0x5b, 0xb5, 0x7c, 0x23, 0xb4, 0x06, 0x50, 0xa2, - 0x62, 0xc2, 0x14, 0x97, 0x7e, 0x12, 0x8a, 0x63, 0x1e, 0x44, 0x0e, 0x89, 0xf9, 0x12, 0x96, 0xa8, - 0x30, 0xd4, 0x43, 0x19, 0x91, 0xe6, 0xc3, 0xd2, 0xa3, 0x3f, 0x53, 0x2d, 0xc0, 0xeb, 0x24, 0x9d, - 0x7f, 0x54, 0x03, 0xb0, 0xbe, 0xd4, 0x7c, 0x65, 0x80, 0xa1, 0x35, 0xda, 0x40, 0xc3, 0x60, 0x0d, - 0xae, 0xe9, 0x97, 0x92, 0x04, 0x97, 0x2c, 0xc4, 0x3c, 0xcd, 0xa4, 0xef, 0xdf, 0xa4, 0x1b, 0x51, - 0x8d, 0xab, 0x6c, 0xed, 0x90, 0xd4, 0xc5, 0x62, 0xa1, 0xb5, 0xc0, 0x71, 0x9c, 0xaa, 0x83, 0x1d, - 0xcd, 0x49, 0x0a, 0x1d, 0x3d, 0x86, 0xc1, 0xdc, 0x19, 0x39, 0xba, 0xd3, 0x72, 0xb9, 0x2c, 0x3b, - 0xd9, 0x31, 0xe8, 0x2d, 0x95, 0x92, 0x11, 0xf8, 0x0f, 0x69, 0xff, 0xf1, 0x67, 0xc2, 0x5e, 0xb1, - 0x14, 0x25, 0xe4, 0xc4, 0x6e, 0xd2, 0x9d, 0x0e, 0xa8, 0xce, 0xd7, 0x28, 0xb8, 0x4e, 0x60, 0x3f, - 0xcb, 0x78, 0xa7, 0x69, 0x75, 0xea, 0x44, 0x32, 0xd7, 0xf7, 0x94, 0x66, 0xec, 0x98, 0x35, 0xcb, - 0x68, 0x1d, 0x27, 0x0f, 0x93, 0x1c, 0x36, 0x64, 0xe5, 0x22, 0x8b, 0x97, 0xfb, 0x05, 0xf2, 0x85, - 0x38, 0xc9, 0x4d, 0x4a, 0x40, 0xe0, 0xa6, 0xd7, 0x51, 0xbc, 0x31, 0xf3, 0xdb, 0x35, 0x82, 0xca, - 0xc3, 0xae, 0xc1, 0x66, 0xa0, 0x1b, 0x5d, 0x43, 0x23, 0x15, 0x36, 0xa0, 0x23, 0x89, 0xb6, 0xb9, - 0x98, 0xe8, 0x07, 0x2d, 0xf9, 0x9c, 0x32, 0x03, 0xc6, 0x43, 0x06, 0x26, 0xa9, 0x40, 0xa5, 0x89, - 0xef, 0xa3, 0x43, 0xde, 0xb0, 0x4d, 0x6f, 0xa3, 0x8c, 0x44, 0x1e, 0x4d, 0x24, 0x07, 0x4d, 0xcd, - 0x7b, 0x44, 0xde, 0x24, 0xde, 0x08, 0x04, 0x84, 0x6b, 0x49, 0xc3, 0xbd, 0xd4, 0xa1, 0x10, 0x6c, - 0x5f, 0xb9, 0xbb, 0x4a, 0xe2, 0x3e, 0x94, 0x6a, 0xbf, 0xf2, 0x6a, 0x25, 0xde, 0x80, 0x4a, 0xb2, - 0x8a, 0x35, 0x7b, 0x99, 0xcd, 0x58, 0x49, 0x74, 0x2d, 0x3a, 0x3c, 0x24, 0x49, 0xa5, 0xc3, 0x25, - 0x2e, 0xe6, 0x8b, 0xb9, 0x18, 0xb6, 0x34, 0x3b, 0x60, 0x7f, 0x58, 0x14, 0xe9, 0x7a, 0x62, 0x85, - 0x78, 0xd6, 0xca, 0xe0, 0x0e, 0xbd, 0xb1, 0x5f, 0x2a, 0x68, 0xbc, 0x21, 0xdc, 0x2d, 0xa5, 0xa7, - 0x95, 0x72, 0xfa, 0x36, 0x5b, 0x46, 0x8d, 0x9c, 0xa1, 0xe3, 0x48, 0x27, 0x09, 0x2a, 0xa6, 0xdc, - 0x49, 0xa7, 0x5b, 0x61, 0x15, 0xf4, 0xd5, 0x80, 0x8e, 0x56, 0x6c, 0x99, 0x05, 0xd4, 0x34, 0x5d, - 0x65, 0x01, 0xd4, 0xe5, 0xd0, 0x33, 0x68, 0xd7, 0xe8, 0xed, 0x99, 0x0b, 0x93, 0x32, 0xa2, 0x42, - 0x40, 0x94, 0x3d, 0x99, 0xdd, 0xc5, 0x5a, 0x20, 0x47, 0x6a, 0x97, 0xe9, 0xfc, 0x36, 0x3f, 0x56, - 0x29, 0x45, 0xa8, 0x8b, 0x6b, 0xf1, 0x23, 0xde, 0x20, 0xb9, 0xa5, 0x88, 0x86, 0x3f, 0x3e, 0x2c, - 0xd3, 0x20, 0xde, 0x7f, 0x11, 0xaf, 0x29, 0x05, 0x8d, 0xa0, 0x06, 0x0c, 0xef, 0x97, 0xe2, 0x61, - 0x2b, 0x66, 0xf3, 0x95, 0x98, 0x7f, 0x44, 0xd7, 0x0f, 0xdd, 0x36, 0x31, 0xad, 0xa4, 0x5b, 0xeb, - 0xb4, 0xb9, 0x5d, 0x5f, 0x8b, 0xec, 0x83, 0x59, 0x2b, 0xda, 0x46, 0x79, 0x7e, 0x8f, 0x6e, 0x8d, - 0x42, 0xb2, 0x95, 0x0f, 0x66, 0x2e, 0x12, 0x84, 0xab, 0xdd, 0xa1, 0xe8, 0xe7, 0xf3, 0x79, 0xa7, - 0xdc, 0x6b, 0x71, 0x90, 0x5a, 0x7b, 0xf8, 0xe7, 0xc8, 0x48, 0xe8, 0x79, 0x8e, 0xc9, 0xff, 0x7c, - 0xc4, 0x43, 0x44, 0xd8, 0x96, 0x47, 0x2a, 0x43, 0x5f, 0x4d, 0x66, 0x2c, 0x44, 0xaf, 0x5e, 0xc2, - 0x2e, 0x99, 0xfd, 0x15, 0x59, 0x86, 0x14, 0x63, 0x65, 0x77, 0x69, 0x66, 0xd8, 0x9e, 0x4c, 0x4d, - 0xcd, 0x0a, 0x95, 0xb2, 0x6c, 0x5a, 0x73, 0x0f, 0x52, 0x2c, 0x13, 0xe8, 0xe2, 0x5c, 0xac, 0xd2, - 0x84, 0xb2, 0x51, 0xed, 0x8e, 0x04, 0xfd, 0x51, 0x0d, 0x94, 0x97, 0xab, 0x8d, 0x30, 0xa9, 0x87, - 0xf5, 0x51, 0xff, 0x90, 0xe4, 0x41, 0x07, 0xc9, 0xde, 0x18, 0x59, 0x45, 0x5f, 0xc1, 0x94, 0x7a, - 0x21, 0x39, 0x2b, 0x5f, 0x9a, 0x03, 0x7c, 0xe9, 0x8f, 0xc6, 0x23, 0x31, 0x9f, 0x56, 0xf6, 0x6d, - 0xcf, 0x8b, 0x8d, 0xce, 0x16, 0xe9, 0xb1, 0x9d, 0x2a, 0x1a, 0xbd, 0xd2, 0xae, 0xd8, 0x15, 0x4d, - 0x6f, 0xb2, 0x98, 0x4d, 0x17, 0x09, 0x86, 0x25, 0x36, 0x8b, 0x89, 0xd7, 0x28, 0xc9, 0x8b, 0x28, - 0x83, 0xf9, 0xc8, 0xb2, 0x2c, 0xbd, 0xaf, 0x37, 0xa1, 0x57, 0x55, 0xcf, 0xc3, 0x9a, 0xd5, 0xd8, - 0xbb, 0x79, 0x22, 0xa2, 0x8c, 0x27, 0x11, 0x5c, 0xa5, 0xe2, 0xbf, 0xc6, 0x82, 0xdc, 0x9b, 0xb0, - 0x22, 0x76, 0x1b, 0xd3, 0x8e, 0xd4, 0xe0, 0xd1, 0xb4, 0x6b, 0xf4, 0xbb, 0x64, 0x5d, 0xed, 0x88, - 0xd8, 0xc8, 0xc1, 0x40, 0xad, 0x2c, 0xba, 0xcf, 0xa2, 0xed, 0x84, 0x2e, 0xc7, 0xf2, 0x12, 0xe5, - 0xb2, 0x69, 0x5c, 0x43, 0x4d, 0x2e, 0xca, 0xf4, 0xac, 0xae, 0xb3, 0xb2, 0x05, 0x95, 0xec, 0x97, - 0x69, 0x4a, 0x5c, 0xab, 0xe9, 0xb9, 0x57, 0x3a, 0x2c, 0xa9, 0xe7, 0x07, 0x41, 0x77, 0xff, 0x65, - 0x74, 0x0d, 0xb1, 0x6b, 0x55, 0x5c, 0xf8, 0xf4, 0x67, 0x6f, 0x5f, 0xa7, 0x8b, 0x87, 0x86, 0x53, - 0x4e, 0xe2, 0x6d, 0xdd, 0xd0, 0x0f, 0xfd, 0xb5, 0x58, 0x2c, 0x9d, 0x65, 0x3b, 0xe7, 0x70, 0x4f, - 0xdb, 0x96, 0xf4, 0x90, 0x54, 0x84, 0x88, 0xc6, 0x39, 0x56, 0x87, 0x14, 0x1b, 0x19, 0x22, 0x5d, - 0xa0, 0x47, 0xdd, 0x2c, 0xdb, 0xdb, 0x14, 0x39, 0x09, 0xb0, 0xd7, 0x08, 0x4f, 0x03, 0xc7, 0xe9, - 0x20, 0xdc, 0xa6, 0x1c, 0xd6, 0xac, 0x75, 0x79, 0x1a, 0x9e, 0xd4, 0x6b, 0x57, 0x3a, 0x74, 0x28, - 0x6e, 0x11, 0xcf, 0xc1, 0x2f, 0xe8, 0xed, 0xf5, 0x2d, 0x22, 0xc2, 0xa6, 0x2b, 0x17, 0x93, 0xd6, - 0xa5, 0x54, 0xcd, 0xe9, 0xc8, 0xcb, 0x6a, 0x31, 0xaf, 0x95, 0xc1, 0xb6, 0xa2, 0x17, 0x33, 0xe1, - 0x98, 0xc2, 0x20, 0x2a, 0xa9, 0xf4, 0x15, 0x69, 0x7a, 0x43, 0x3b, 0xdc, 0x21, 0xa1, 0x0e, 0x24, - 0xa5, 0x7b, 0x51, 0xa8, 0x3e, 0x32, 0x7b, 0x41, 0x73, 0xeb, 0x3a, 0xca, 0x76, 0x75, 0x43, 0xbe, - 0x81, 0xd2, 0x52, 0x8c, 0xa8, 0x4c, 0x97, 0x4a, 0x98, 0x59, 0x4f, 0xb4, 0xcd, 0xbc, 0xc8, 0x44, - 0x31, 0x5f, 0x1d, 0x8a, 0xf5, 0x84, 0x45, 0xc8, 0x84, 0x55, 0x05, 0x5e, 0x72, 0xc8, 0x75, 0xe9, - 0x68, 0xfd, 0x59, 0x32, 0x80, 0x2d, 0x08, 0xaa, 0x0f, 0xc7, 0x90, 0xd9, 0xbd, 0x94, 0x23, 0xd6, - 0x42, 0xe0, 0x41, 0x19, 0x63, 0x53, 0x16, 0x62, 0xd6, 0x4d, 0x05, 0xf5, 0x86, 0x15, 0xba, 0x07, - 0xf3, 0xaa, 0x66, 0x62, 0xc0, 0xa6, 0x77, 0x6c, 0x4a, 0x20, 0xf3, 0xc5, 0x7c, 0x05, 0xfe, 0x21, - 0xe1, 0xee, 0x4a, 0x51, 0x49, 0x15, 0x9a, 0x63, 0xb6, 0x33, 0x96, 0xca, 0x1d, 0xb4, 0xa0, 0x31, - 0x1f, 0x76, 0x0a, 0x0d, 0xf6, 0x1c, 0x2d, 0x9d, 0xaa, 0xd6, 0x2b, 0x0e, 0xe7, 0xfb, 0x4a, 0xd5, - 0xbf, 0x2e, 0xa7, 0x7b, 0x3a, 0x53, 0x19, 0x60, 0x84, 0xbb, 0x9b, 0xe6, 0x7c, 0xad, 0xb1, 0xdc, - 0xc1, 0xb6, 0xae, 0x66, 0x7f, 0x2c, 0x11, 0x34, 0xb7, 0xc4, 0xae, 0x26, 0x35, 0x56, 0x42, 0x65, - 0x6f, 0xbb, 0xfa, 0xda, 0x49, 0x7d, 0x31, 0xa5, 0x02, 0x86, 0xb6, 0xa0, 0xc6, 0xac, 0x08, 0xb3, - 0xef, 0x2d, 0x0b, 0xa4, 0x50, 0x6e, 0xda, 0x4c, 0xd1, 0x91, 0xbd, 0xdf, 0xdc, 0xd0, 0x0c, 0xed, - 0xa4, 0xed, 0x48, 0x7f, 0xcc, 0x03, 0x96, 0x09, 0x31, 0xe5, 0x3c, 0x52, 0x52, 0xd5, 0xf4, 0xa4, - 0x21, 0x23, 0x09, 0xd9, 0xca, 0xef, 0x63, 0x28, 0x6d, 0x4d, 0x4e, 0x93, 0x8e, 0x7c, 0x84, 0xb3, - 0x8a, 0xce, 0x41, 0x55, 0xaa, 0xe1, 0x77, 0xeb, 0x44, 0x3d, 0xb3, 0x28, 0x07, 0x40, 0x0e, 0x31, - 0xcc, 0xa7, 0xb0, 0x4f, 0xf8, 0x17, 0x4c, 0x14, 0xa5, 0xeb, 0x5a, 0x63, 0x76, 0x96, 0x68, 0x25, - 0x1a, 0x8e, 0x58, 0xef, 0xeb, 0x08, 0xea, 0x90, 0xdd, 0x2c, 0x3c, 0x58, 0xe7, 0x69, 0xf7, 0x52, - 0x0d, 0x6a, 0xd4, 0x11, 0xee, 0x51, 0x66, 0xdd, 0x10, 0x65, 0xe8, 0x73, 0xe6, 0x8e, 0x9c, 0x85, - 0xb8, 0x31, 0x49, 0x2d, 0x0d, 0xc7, 0xfc, 0x52, 0x08, 0xd1, 0xef, 0x58, 0x7a, 0x6b, 0x84, 0x47, - 0x66, 0x6d, 0x3b, 0x3c, 0x0e, 0xdb, 0xe1, 0x51, 0xcf, 0x42, 0x07, 0x94, 0x6a, 0xf3, 0x42, 0xd0, - 0xb6, 0x63, 0x1d, 0x40, 0x6a, 0x63, 0x33, 0x09, 0xa3, 0xd6, 0x92, 0x49, 0x4a, 0xe9, 0x06, 0x15, - 0x3b, 0xa4, 0x67, 0x33, 0xfe, 0x55, 0x32, 0x71, 0xeb, 0x3f, 0x4e, 0xd4, 0x10, 0xbe, 0x12, 0xf3, - 0x64, 0x4a, 0x8d, 0x27, 0x7c, 0x15, 0x8b, 0xe7, 0x27, 0xf4, 0x46, 0x4e, 0x3e, 0x1f, 0xeb, 0xa2, - 0x91, 0x65, 0x9e, 0xf8, 0xd2, 0xc3, 0xc9, 0x0e, 0xbb, 0x43, 0xee, 0xdc, 0xc5, 0x79, 0x7c, 0x1d, - 0x27, 0xb4, 0x08, 0x2c, 0xe7, 0xef, 0xa5, 0x80, 0xe5, 0xec, 0xaa, 0x6e, 0x6b, 0xc3, 0x6e, 0x15, - 0x24, 0xa7, 0x8a, 0x41, 0xfe, 0xb0, 0x16, 0x8b, 0x38, 0x32, 0xf2, 0x79, 0x26, 0xc4, 0xc6, 0x88, - 0xa0, 0x86, 0x67, 0xb5, 0xb4, 0x63, 0x0c, 0xd2, 0xfb, 0x3b, 0xce, 0xc4, 0xda, 0x41, 0xc1, 0x3d, - 0x08, 0x0a, 0xca, 0xa8, 0x75, 0xe7, 0x90, 0x16, 0x1a, 0xea, 0x39, 0xcc, 0xf0, 0xeb, 0x69, 0x7a, - 0xfd, 0x77, 0xb8, 0x50, 0x6b, 0x19, 0x23, 0x86, 0x41, 0x39, 0x31, 0xdf, 0xad, 0x16, 0x22, 0x98, - 0x26, 0xe8, 0xfa, 0x01, 0xae, 0x2a, 0x49, 0xa4, 0x89, 0x36, 0x05, 0x88, 0x0d, 0xcd, 0x16, 0x9e, - 0x14, 0xba, 0x4f, 0x13, 0x17, 0x06, 0x21, 0x13, 0x77, 0x1c, 0xae, 0x7b, 0x08, 0xd7, 0x7d, 0x1c, - 0x6e, 0xe0, 0x8c, 0x18, 0xae, 0x8e, 0xa6, 0x27, 0x63, 0x87, 0x8e, 0x6d, 0xe5, 0xc2, 0x4e, 0x33, - 0xa6, 0x54, 0xce, 0xa9, 0x8c, 0x57, 0xb4, 0xd2, 0x1e, 0xdd, 0x45, 0x71, 0x42, 0x59, 0x78, 0x6d, - 0x91, 0xa6, 0xbe, 0xdc, 0x52, 0x87, 0x68, 0x44, 0x70, 0x99, 0xc5, 0x99, 0x5a, 0x1b, 0xe9, 0x1f, - 0xf8, 0x51, 0xb5, 0x74, 0xd2, 0x58, 0x06, 0xa9, 0x2f, 0xed, 0xc8, 0x55, 0x8c, 0x47, 0x17, 0x65, - 0xaa, 0x4c, 0x7b, 0x14, 0x7e, 0x6d, 0x3a, 0x7d, 0x9d, 0xe1, 0x0c, 0x23, 0xfa, 0xa3, 0xfb, 0xdb, - 0x99, 0xc8, 0xb7, 0x29, 0x0c, 0xfa, 0x4e, 0xec, 0x3a, 0xe4, 0x7c, 0xd0, 0x48, 0x2d, 0xcf, 0x1c, - 0x8b, 0x5a, 0x8e, 0x5e, 0xad, 0x3e, 0xec, 0x18, 0x75, 0x12, 0x43, 0x44, 0xb7, 0xd7, 0x39, 0x65, - 0xd4, 0xb1, 0x8a, 0x78, 0xf3, 0xd0, 0x64, 0xce, 0x69, 0x31, 0x0f, 0xc2, 0x31, 0x89, 0xb9, 0xb9, - 0x0a, 0xc2, 0x7c, 0xe7, 0x54, 0xba, 0xa9, 0xa0, 0x87, 0xfa, 0x59, 0x8b, 0x8c, 0xc8, 0x44, 0x6b, - 0xda, 0xe0, 0x96, 0x49, 0xe7, 0xd1, 0x54, 0xd5, 0x69, 0x01, 0x93, 0xb3, 0xb7, 0x5d, 0x33, 0x3f, - 0xa8, 0xa6, 0xe6, 0x86, 0x54, 0xda, 0x17, 0xe7, 0x72, 0x53, 0xe9, 0xdf, 0xff, 0xed, 0xc5, 0xb9, - 0xda, 0xf1, 0xc2, 0x23, 0x21, 0x6b, 0xcc, 0x13, 0x4c, 0xcf, 0x67, 0xf4, 0x58, 0xee, 0x64, 0xc1, - 0x34, 0x8d, 0x78, 0x31, 0xa3, 0x3b, 0xe5, 0x4d, 0xaa, 0x9c, 0xeb, 0xe4, 0x6a, 0x95, 0xea, 0xd4, - 0xc3, 0xc8, 0x86, 0x2c, 0xe9, 0xd5, 0x1a, 0x71, 0xc3, 0x45, 0x7c, 0xa7, 0x5a, 0xd5, 0x77, 0xc9, - 0x1a, 0x4d, 0xd8, 0x5d, 0x19, 0xa0, 0x76, 0xd6, 0xa3, 0xd5, 0x35, 0x52, 0x6f, 0xd1, 0xd3, 0xa0, - 0x29, 0x9f, 0x90, 0x89, 0x6b, 0x1b, 0x74, 0x63, 0x08, 0xa0, 0x49, 0x2d, 0xa9, 0xbf, 0xc1, 0x03, - 0xcd, 0x9e, 0x5d, 0x26, 0xf1, 0xfc, 0xa3, 0x51, 0xa4, 0xc6, 0xed, 0x96, 0xd6, 0xfe, 0x8d, 0x87, - 0xf4, 0x36, 0x33, 0xb8, 0x01, 0x0d, 0xf0, 0xec, 0xe2, 0xc5, 0x39, 0x3a, 0x76, 0xe1, 0x73, 0xce, - 0x08, 0x75, 0xd5, 0xac, 0x5c, 0x1a, 0x88, 0xb6, 0xeb, 0xe4, 0x48, 0x12, 0x47, 0x25, 0xa1, 0xd6, - 0xa6, 0xe0, 0xca, 0x3d, 0x0e, 0x01, 0xd6, 0x93, 0x43, 0x95, 0x5b, 0xfd, 0x3b, 0xfa, 0x74, 0xe1, - 0x58, 0x67, 0xa9, 0x34, 0x48, 0x40, 0xc4, 0x93, 0x85, 0xc7, 0xae, 0x21, 0x91, 0x94, 0xb3, 0x18, - 0x7b, 0xa8, 0xb7, 0x10, 0xfb, 0x3e, 0x1e, 0x65, 0x64, 0xc4, 0x6c, 0x14, 0x05, 0xaf, 0x67, 0x6a, - 0x01, 0x44, 0xdc, 0xc7, 0x90, 0xae, 0xa3, 0x67, 0x2c, 0xa2, 0x22, 0x22, 0x65, 0xa0, 0xad, 0x4d, - 0xf8, 0x4c, 0x3c, 0xf5, 0x2e, 0xfe, 0x12, 0x7f, 0x1f, 0x1b, 0xef, 0x44, 0x71, 0xbb, 0x7d, 0x71, - 0x1e, 0x75, 0x72, 0x94, 0x70, 0xe8, 0xaa, 0xe0, 0x11, 0x79, 0x2e, 0x6a, 0x20, 0x5b, 0xbf, 0x11, - 0xc5, 0xec, 0xff, 0x5d, 0x27, 0x11, 0x86, 0x83, 0x3f, 0x98, 0x6d, 0xd2, 0x74, 0x2b, 0x36, 0xd0, - 0xb2, 0x55, 0x26, 0x96, 0x33, 0xfb, 0x1c, 0x86, 0x58, 0x5c, 0x7c, 0x0f, 0xd9, 0xe5, 0x47, 0x86, - 0xf9, 0x55, 0xd0, 0x6e, 0xb7, 0x20, 0x45, 0x5c, 0xfc, 0x99, 0x6f, 0xff, 0x3a, 0xc0, 0x55, 0x51, - 0x6c, 0xf3, 0xc9, 0xf9, 0xf9, 0x75, 0x72, 0x4b, 0x31, 0x7c, 0x2e, 0x32, 0xfb, 0x26, 0x2e, 0x56, - 0xb7, 0xd7, 0x76, 0x9c, 0x9e, 0x47, 0xf7, 0x45, 0x16, 0x7f, 0x02, 0x23, 0xa1, 0x19, 0x17, 0xdf, - 0xa5, 0xf3, 0xe3, 0x04, 0x34, 0x99, 0x4e, 0x8e, 0xaf, 0x47, 0x38, 0xac, 0x6e, 0xd7, 0x16, 0x62, - 0xc9, 0x29, 0x0b, 0x90, 0x3d, 0x61, 0x04, 0x06, 0x9b, 0xf8, 0x4c, 0xe5, 0xba, 0x16, 0xbc, 0xcc, - 0x91, 0x6e, 0x52, 0x3b, 0xd0, 0x41, 0x19, 0xcf, 0x5a, 0x6c, 0x6e, 0xc9, 0x36, 0x92, 0x99, 0xca, - 0xb7, 0x2f, 0x79, 0xa9, 0x8b, 0x36, 0xa6, 0xff, 0x48, 0x02, 0xa7, 0x34, 0xc8, 0x83, 0x27, 0x19, - 0xf5, 0xa0, 0xaa, 0xe8, 0x70, 0x0c, 0x9b, 0xa3, 0x76, 0xd5, 0xa6, 0xb9, 0xdd, 0x52, 0xfa, 0x24, - 0x91, 0xd5, 0x8b, 0x94, 0x71, 0x6b, 0x65, 0xab, 0x7b, 0x9c, 0x74, 0x5b, 0x48, 0xfd, 0x6b, 0x41, - 0x5d, 0x79, 0x4d, 0xc3, 0xb2, 0xbc, 0x8b, 0x4b, 0x19, 0xda, 0xc9, 0x1b, 0x90, 0xb2, 0x62, 0x20, - 0xaf, 0xcb, 0xaa, 0xf4, 0x40, 0xbc, 0xba, 0xa5, 0x81, 0x20, 0x30, 0x74, 0x51, 0x53, 0x6f, 0xc3, - 0xcf, 0xc7, 0xd8, 0x51, 0xb0, 0x7b, 0xd5, 0xa0, 0x93, 0x38, 0x2f, 0xc0, 0xbe, 0xa2, 0xe6, 0x68, - 0x9b, 0x2c, 0x39, 0x06, 0xeb, 0xc5, 0x75, 0xf6, 0xeb, 0x9c, 0x43, 0x3d, 0xa7, 0xe9, 0x82, 0x47, - 0xe1, 0x45, 0x35, 0xa5, 0xc7, 0xc7, 0x75, 0xab, 0x9a, 0x6c, 0x9f, 0x52, 0xa8, 0xca, 0x9b, 0xe7, - 0x79, 0xbc, 0x50, 0x5d, 0x6b, 0xab, 0xfe, 0x17, 0xef, 0xde, 0xfd, 0xf0, 0xdd, 0x71, 0x1f, 0x5b, - 0xc2, 0xe1, 0x2e, 0x46, 0xb9, 0x46, 0x6c, 0xd4, 0x96, 0x50, 0x67, 0xbd, 0x57, 0x34, 0xd5, 0x93, - 0x1e, 0x1d, 0xf2, 0xfc, 0xc1, 0x20, 0x98, 0x7c, 0x8c, 0x82, 0xad, 0xa5, 0x47, 0x23, 0xf7, 0xca, - 0x83, 0x14, 0x87, 0x3c, 0xee, 0x56, 0xd0, 0x7f, 0x91, 0x5c, 0xbd, 0xbc, 0xdd, 0x41, 0xf2, 0x5b, - 0x55, 0xf5, 0x04, 0xb2, 0x6b, 0xa6, 0xdc, 0x98, 0xda, 0xb3, 0x91, 0x96, 0x25, 0x7a, 0xac, 0x13, - 0x90, 0x18, 0x5a, 0xe9, 0x50, 0xca, 0xae, 0x46, 0x35, 0x9d, 0xee, 0x95, 0x30, 0x09, 0xdc, 0x23, - 0xa0, 0xda, 0xc8, 0xc1, 0xfc, 0xd9, 0x77, 0x94, 0xaf, 0x96, 0xd0, 0x7e, 0x44, 0x3c, 0x88, 0x96, - 0xd3, 0x18, 0xe0, 0xaf, 0x76, 0x1a, 0xa7, 0xb8, 0x5f, 0x0e, 0xd4, 0xe9, 0x1e, 0x1f, 0xa1, 0x4c, - 0x3a, 0x4a, 0xcd, 0x9d, 0xdf, 0x8e, 0x9c, 0x4d, 0xfa, 0xbb, 0x53, 0xf4, 0x18, 0x84, 0xba, 0x31, - 0x94, 0x6a, 0x76, 0xc2, 0x20, 0x62, 0x43, 0xb7, 0x62, 0xa6, 0xe8, 0x97, 0xd3, 0x28, 0xd2, 0xda, - 0xd0, 0x3c, 0x5d, 0x6f, 0x13, 0x51, 0x08, 0x1d, 0x01, 0x4a, 0x45, 0x93, 0x71, 0x7f, 0x9d, 0x23, - 0x48, 0xd0, 0xbe, 0xce, 0xac, 0x57, 0x0d, 0xf0, 0x6b, 0xcd, 0xec, 0xc5, 0x79, 0x87, 0xbb, 0x79, - 0xc4, 0x97, 0xf5, 0xd4, 0x44, 0xca, 0xe8, 0xca, 0x5d, 0x94, 0x0d, 0xaa, 0x96, 0x72, 0x0e, 0x6c, - 0xe8, 0x6d, 0xd9, 0xa3, 0xc9, 0xce, 0xea, 0x98, 0x59, 0xcb, 0x84, 0x49, 0x27, 0x58, 0xd5, 0x84, - 0xfa, 0xe2, 0x5d, 0x81, 0xb9, 0xb9, 0x64, 0x2f, 0x66, 0x03, 0x74, 0x94, 0x27, 0x8e, 0x92, 0xfc, - 0x68, 0x72, 0xc3, 0xb0, 0xa4, 0xe0, 0x48, 0x06, 0x94, 0xf2, 0xe5, 0xb4, 0x14, 0x63, 0x34, 0x36, - 0xd5, 0x4a, 0xb4, 0xe5, 0x3c, 0x1f, 0x79, 0xaf, 0x5c, 0x19, 0x78, 0x82, 0x7f, 0xaa, 0xaf, 0x1c, - 0xfc, 0x33, 0xd9, 0xac, 0x4c, 0xf7, 0xe6, 0xd1, 0xa6, 0x91, 0xef, 0x81, 0xd3, 0x27, 0x33, 0xed, - 0x96, 0xc1, 0x28, 0x23, 0x21, 0x30, 0x8f, 0xe6, 0x0e, 0x4f, 0x35, 0x1a, 0x96, 0xc0, 0xc5, 0x3b, - 0x02, 0xc9, 0xdc, 0xde, 0x88, 0x02, 0xaa, 0xf6, 0xf1, 0x38, 0xab, 0x4f, 0xa5, 0x6f, 0x2a, 0x02, - 0xfe, 0x06, 0x34, 0x2a, 0x48, 0xbf, 0x31, 0x99, 0xb5, 0xd4, 0xa4, 0x4c, 0xd5, 0x29, 0x7e, 0x59, - 0x14, 0xce, 0x54, 0xb0, 0x7c, 0x32, 0xd9, 0x87, 0x19, 0x55, 0xeb, 0x5d, 0x65, 0x39, 0x6c, 0x4e, - 0x95, 0xf2, 0x69, 0xeb, 0x62, 0x37, 0xda, 0x06, 0xd9, 0x61, 0x5d, 0x9d, 0x56, 0x78, 0x60, 0x50, - 0xdd, 0xaa, 0x27, 0xa5, 0x82, 0x59, 0x3a, 0x2d, 0xcf, 0x3f, 0x22, 0x90, 0x13, 0xc2, 0xd0, 0x00, - 0x7e, 0x0b, 0x61, 0x48, 0x41, 0xfc, 0x49, 0x41, 0x7c, 0xf5, 0xee, 0x6d, 0x27, 0xc7, 0x3b, 0xb8, - 0x2d, 0x2d, 0x28, 0xba, 0xa3, 0x90, 0x93, 0x45, 0xeb, 0xfc, 0x9f, 0x27, 0x87, 0x80, 0xfc, 0x86, - 0xb4, 0xbc, 0x23, 0x70, 0xd0, 0xd7, 0x65, 0x7c, 0x73, 0x2b, 0xcf, 0xd5, 0x3c, 0x81, 0xa4, 0x3a, - 0xc8, 0x17, 0xe7, 0x34, 0xeb, 0xd7, 0x2f, 0x35, 0x47, 0x2c, 0x0f, 0xf1, 0x19, 0x65, 0xc0, 0x95, - 0xef, 0x17, 0x57, 0x29, 0xa7, 0xda, 0xb6, 0x6d, 0x37, 0xa0, 0xa8, 0xc3, 0x2d, 0xbc, 0x8a, 0xc0, - 0x47, 0x9f, 0xd6, 0x22, 0xcf, 0xa3, 0x9b, 0x7a, 0x7e, 0xfb, 0x42, 0x1d, 0x76, 0x21, 0xba, 0xd4, - 0x53, 0x4b, 0x5f, 0xe5, 0xc8, 0xea, 0xf0, 0xd4, 0xa1, 0x08, 0xd2, 0xcd, 0x9c, 0x66, 0xfa, 0x33, - 0x3e, 0x2c, 0xf6, 0x86, 0xda, 0xbc, 0x91, 0x83, 0x9c, 0xf5, 0x4f, 0xcb, 0xa0, 0x71, 0xca, 0xec, - 0xa8, 0x8d, 0x4a, 0x19, 0x71, 0x1b, 0xd9, 0xde, 0x90, 0x67, 0x7a, 0xdd, 0x81, 0x21, 0x97, 0xb1, - 0xe9, 0xa9, 0x21, 0x27, 0xbc, 0xbb, 0x83, 0x9e, 0x94, 0x26, 0x2d, 0x22, 0x1d, 0x9d, 0x2d, 0x75, - 0x06, 0xbd, 0x43, 0x2d, 0x3b, 0xc4, 0xf8, 0xe8, 0x52, 0x0a, 0xa6, 0x3e, 0xc4, 0x6a, 0x49, 0xbf, - 0x6a, 0xd6, 0x35, 0xd9, 0x39, 0x1d, 0x6d, 0x5b, 0xe7, 0xd4, 0xba, 0x06, 0xda, 0xd6, 0xc7, 0xe1, - 0xb9, 0xcc, 0x8b, 0xf3, 0xed, 0xaf, 0x1b, 0x45, 0x39, 0x9d, 0xa3, 0x8e, 0x3b, 0xfd, 0xa8, 0xf8, - 0x5d, 0x19, 0x95, 0x52, 0xbb, 0xe3, 0x12, 0x2f, 0xb2, 0x5b, 0xd1, 0xbf, 0x90, 0x36, 0xf0, 0xd3, - 0xff, 0x55, 0x3a, 0x7f, 0x32, 0x3a, 0xd4, 0xe4, 0x5a, 0x33, 0xde, 0x13, 0x43, 0x2c, 0x11, 0xf3, - 0xcb, 0x31, 0x2e, 0xa9, 0xfa, 0xe8, 0x30, 0xa7, 0xbc, 0x31, 0x9e, 0xa5, 0x6d, 0x94, 0xa7, 0xbd, - 0xe7, 0x59, 0xbc, 0x2d, 0x2e, 0xa0, 0x29, 0x57, 0xe9, 0x4d, 0x3a, 0x7b, 0xc6, 0x9a, 0x27, 0x55, - 0x2d, 0xa0, 0xb3, 0x1e, 0x4a, 0xd9, 0xf8, 0xb9, 0xe9, 0x16, 0x46, 0xf8, 0x0b, 0xb7, 0xb0, 0x8d, - 0x8a, 0x95, 0x81, 0xc9, 0xcf, 0x1b, 0xd7, 0xb3, 0xc7, 0x5e, 0x60, 0xb8, 0x63, 0xdb, 0xf7, 0x06, - 0x51, 0x68, 0x07, 0x06, 0xfd, 0xe3, 0x6d, 0x0c, 0x0b, 0x55, 0x23, 0xdf, 0x0a, 0xec, 0x70, 0x38, - 0x40, 0xe9, 0x40, 0x5d, 0x64, 0x9d, 0x6f, 0x8f, 0xbc, 0x91, 0xe5, 0xda, 0xc3, 0xe1, 0xc0, 0x0e, - 0xc6, 0x21, 0xfd, 0x93, 0x5b, 0x1f, 0x96, 0x1d, 0x38, 0x81, 0x65, 0x87, 0xbe, 0x6b, 0x07, 0xe1, - 0x80, 0xfe, 0xc9, 0x72, 0xc3, 0x0e, 0x07, 0x3e, 0x2a, 0xdd, 0xd0, 0x18, 0xd9, 0x63, 0x75, 0x91, - 0x35, 0x23, 0x63, 0x6c, 0x8f, 0x9c, 0x21, 0xc0, 0x03, 0xa6, 0xba, 0x2a, 0x58, 0xde, 0x78, 0x64, - 0x60, 0x90, 0x81, 0x97, 0xb8, 0x40, 0x66, 0x6c, 0x0f, 0x83, 0xc8, 0x75, 0x6d, 0xc7, 0x1f, 0x1b, - 0xea, 0xa6, 0x36, 0x5c, 0xec, 0xd0, 0x1d, 0x00, 0xf8, 0xd0, 0x35, 0x40, 0x90, 0x3b, 0x1c, 0xeb, - 0x9b, 0xac, 0xb6, 0x3d, 0x37, 0x04, 0x35, 0xfe, 0xc0, 0x7f, 0x89, 0xf2, 0x61, 0x68, 0xc8, 0xab, - 0xac, 0x0c, 0x51, 0xeb, 0x19, 0x81, 0xed, 0x86, 0x6e, 0x34, 0xb4, 0x87, 0xbe, 0xc1, 0x17, 0xc5, - 0x01, 0x5c, 0x07, 0xb6, 0x0f, 0xfa, 0xe5, 0x55, 0xf3, 0xc5, 0x05, 0xc7, 0x6c, 0xdf, 0x0f, 0x51, - 0xec, 0x85, 0x03, 0x75, 0xd5, 0xa8, 0x8c, 0x9d, 0x31, 0xc0, 0x8d, 0x86, 0x01, 0x91, 0x35, 0xd6, - 0x57, 0x5d, 0xeb, 0x80, 0x29, 0xee, 0x78, 0x88, 0x3e, 0x8e, 0xeb, 0xaa, 0xab, 0x64, 0x83, 0xcf, - 0x10, 0x7d, 0x7b, 0x8c, 0x81, 0x70, 0x0d, 0x86, 0xea, 0xaa, 0xd9, 0x0a, 0x8f, 0x8e, 0x81, 0xc1, - 0x08, 0x3f, 0x74, 0xed, 0xd1, 0x28, 0x72, 0x1d, 0xdb, 0x1d, 0x79, 0x86, 0xba, 0x49, 0xf8, 0x9e, - 0xed, 0x0c, 0x43, 0x10, 0xea, 0x81, 0xac, 0xa1, 0xba, 0x28, 0x1e, 0x40, 0x8a, 0xc0, 0x3c, 0xf0, - 0x46, 0x6b, 0x42, 0x7f, 0x00, 0x09, 0xbd, 0x74, 0x7d, 0xa0, 0xe3, 0x1b, 0xea, 0xa6, 0xc4, 0xe4, - 0x38, 0x2e, 0xc1, 0x84, 0xe8, 0x89, 0x4d, 0x63, 0x1a, 0x41, 0xde, 0x34, 0x96, 0x54, 0x81, 0xde, - 0x61, 0x42, 0x12, 0x25, 0xc1, 0x47, 0x68, 0xe0, 0x04, 0xcc, 0x55, 0xba, 0x39, 0x9a, 0xd6, 0xd0, - 0x76, 0x07, 0xae, 0xd1, 0x55, 0xa9, 0xaa, 0x9c, 0x44, 0xeb, 0x0e, 0x81, 0x18, 0x73, 0xa3, 0x52, - 0x8f, 0xa0, 0x91, 0x7e, 0x80, 0xe1, 0x42, 0x2f, 0x78, 0x83, 0x68, 0x46, 0x28, 0x8d, 0x81, 0x32, - 0xdf, 0xd4, 0x9b, 0x86, 0x86, 0x5e, 0x03, 0xc8, 0x3a, 0x81, 0x3e, 0xba, 0x40, 0x09, 0x2c, 0x80, - 0xe6, 0x0c, 0x3d, 0x20, 0xe9, 0x45, 0x2e, 0x14, 0x0d, 0xf2, 0x55, 0x37, 0x49, 0x03, 0x74, 0x67, - 0x38, 0x1a, 0xf1, 0x2d, 0x0c, 0x12, 0xd2, 0x55, 0xb4, 0x0f, 0xfc, 0xb9, 0x63, 0xd9, 0x7e, 0x10, - 0x00, 0xcf, 0x31, 0x29, 0xb0, 0xc7, 0x0f, 0x0c, 0x72, 0x8d, 0x9b, 0x17, 0x8c, 0xa1, 0x1a, 0x6e, - 0x30, 0x7c, 0x09, 0xec, 0xa1, 0x21, 0xf2, 0xaa, 0x75, 0x68, 0xe4, 0x92, 0xa2, 0x7a, 0x21, 0xa9, - 0xa7, 0xeb, 0xb2, 0x7a, 0xd2, 0x4d, 0x2b, 0xcc, 0x80, 0x94, 0xce, 0x0e, 0xc3, 0x3b, 0x58, 0x85, - 0x3f, 0x24, 0xc6, 0x8f, 0xa9, 0x91, 0xbc, 0x29, 0xa4, 0xc6, 0x18, 0x62, 0x44, 0x88, 0x0e, 0xc3, - 0x15, 0x35, 0x1b, 0x10, 0xac, 0xd0, 0xf5, 0x0d, 0x75, 0x2b, 0x55, 0x3d, 0x74, 0x09, 0xe2, 0x20, - 0x78, 0x13, 0xc2, 0x76, 0x09, 0x8f, 0xd1, 0x08, 0x6d, 0xc1, 0x46, 0x00, 0xe1, 0x2b, 0x83, 0xb3, - 0xe8, 0xd9, 0xaa, 0x17, 0xeb, 0x4a, 0xae, 0xc6, 0xb3, 0x2c, 0xa0, 0x49, 0x99, 0x0c, 0x3a, 0xcf, - 0xa6, 0x70, 0xe2, 0x79, 0x61, 0xe0, 0xf9, 0x8d, 0xd8, 0xdc, 0xc2, 0xad, 0x94, 0x6e, 0xc2, 0x37, - 0x83, 0xd7, 0x9e, 0xfb, 0x7e, 0xf4, 0xda, 0x7f, 0x1f, 0xe0, 0xc5, 0x75, 0xe9, 0xcd, 0xf5, 0xf1, - 0xea, 0xba, 0xf4, 0xce, 0xb5, 0x2e, 0x55, 0xbb, 0xc1, 0x5f, 0x7b, 0xe7, 0x17, 0xcf, 0x4c, 0xf6, - 0x4d, 0x70, 0x8a, 0xd2, 0x37, 0x29, 0x87, 0xd4, 0x73, 0x83, 0x6d, 0xd1, 0x6b, 0xba, 0xa4, 0x21, - 0xc4, 0x82, 0x7f, 0x35, 0xa7, 0xb4, 0x26, 0xc1, 0xa3, 0x68, 0x65, 0x79, 0xa3, 0xd1, 0xdc, 0xf2, - 0x02, 0xb0, 0xcf, 0x77, 0x3d, 0x58, 0x82, 0x35, 0x18, 0x59, 0x1e, 0xa4, 0xe6, 0xc1, 0x94, 0x47, - 0xf4, 0x32, 0x18, 0xdd, 0x59, 0x9e, 0x37, 0x80, 0xe4, 0xa8, 0x55, 0x18, 0x0c, 0x03, 0xcf, 0xa0, - 0x06, 0x83, 0x60, 0x14, 0x0e, 0x51, 0x6b, 0x70, 0x9b, 0x15, 0xc1, 0xa9, 0x81, 0x41, 0xa9, 0x51, - 0x82, 0x31, 0xb8, 0xd5, 0x1d, 0x43, 0x31, 0x4a, 0x28, 0x56, 0x09, 0x45, 0x82, 0xc0, 0xf5, 0xf3, - 0x9a, 0xf0, 0x91, 0x38, 0x8d, 0x20, 0x70, 0x46, 0xc8, 0x25, 0x87, 0xe9, 0x06, 0xe1, 0x98, 0x78, - 0x0d, 0xaf, 0x10, 0x28, 0x40, 0x68, 0xe0, 0x7b, 0x8e, 0xef, 0x52, 0x2d, 0x01, 0xe1, 0x3a, 0xfc, - 0x65, 0x54, 0x74, 0x6f, 0xbc, 0x5b, 0xba, 0x37, 0x3d, 0xa3, 0xb7, 0xa2, 0x46, 0x77, 0xb7, 0x64, - 0x77, 0x8b, 0x2b, 0xf1, 0xf7, 0xf3, 0x1a, 0x2c, 0x03, 0x7f, 0x6b, 0xbc, 0x72, 0xe0, 0x17, 0xd0, - 0xa7, 0xec, 0xc2, 0x48, 0x59, 0x35, 0xa4, 0x18, 0xec, 0xc8, 0x01, 0xd4, 0x21, 0x39, 0xfb, 0x71, - 0x00, 0x22, 0xc8, 0x4a, 0x42, 0x34, 0xf6, 0xac, 0x71, 0x20, 0xff, 0xe6, 0xf8, 0x67, 0xd4, 0x8b, - 0x8d, 0x71, 0x70, 0x47, 0xbd, 0x8c, 0x3a, 0x2e, 0x35, 0x54, 0x71, 0xcd, 0x8f, 0x8e, 0x14, 0x3a, - 0xf6, 0x70, 0xec, 0x83, 0x6e, 0x78, 0xa3, 0x81, 0x13, 0x78, 0xa0, 0x00, 0x4e, 0xdd, 0xa5, 0x90, - 0xe1, 0x8d, 0x72, 0x7a, 0xd6, 0x15, 0x86, 0xaa, 0x78, 0x6c, 0xac, 0x92, 0x72, 0xa9, 0xaa, 0xa4, - 0x5f, 0x7f, 0xde, 0x24, 0xff, 0x5f, 0xc3, 0x7e, 0x7f, 0x0d, 0x1b, 0x39, 0x4f, 0x56, 0xb0, 0x5f, - 0x2f, 0xf6, 0x5f, 0xab, 0x5f, 0xbf, 0x83, 0x16, 0x77, 0x68, 0x16, 0x2d, 0x27, 0xd4, 0xdd, 0x1f, - 0x05, 0x10, 0xef, 0x72, 0x2c, 0x43, 0x14, 0x40, 0x71, 0x54, 0x43, 0x34, 0x0b, 0x90, 0x2b, 0xc1, - 0x89, 0x8f, 0xae, 0x06, 0x36, 0x87, 0x93, 0xc1, 0x25, 0x02, 0xbf, 0xcb, 0x11, 0x1f, 0x17, 0xdf, - 0xa0, 0x3c, 0xc4, 0x18, 0xbf, 0xa3, 0x70, 0x37, 0x96, 0xa5, 0xe4, 0xe5, 0xb9, 0xe5, 0x15, 0x1c, - 0x3d, 0x92, 0x06, 0x80, 0xc5, 0x43, 0x10, 0x18, 0x32, 0x46, 0x0d, 0x47, 0xfa, 0x81, 0x6b, 0xc0, - 0x2c, 0x9f, 0x0b, 0xa0, 0x34, 0x1c, 0x87, 0x29, 0x55, 0xe3, 0xfc, 0x04, 0xcf, 0x21, 0x1a, 0x0c, - 0xa0, 0x71, 0xba, 0xdc, 0xe7, 0xab, 0x27, 0xff, 0xbe, 0xf1, 0x80, 0xc6, 0x95, 0xe7, 0x01, 0x2f, - 0x20, 0x79, 0x89, 0x61, 0xc3, 0x31, 0x25, 0x31, 0x03, 0x82, 0x85, 0x5c, 0x8b, 0xc1, 0xfa, 0xef, - 0x90, 0xb9, 0xb8, 0xaa, 0xd8, 0xa6, 0x24, 0x28, 0xb8, 0x02, 0xd2, 0x97, 0x18, 0x81, 0xb4, 0x8a, - 0x28, 0x85, 0xb6, 0x33, 0xd0, 0xe0, 0x1d, 0x23, 0xc5, 0xa5, 0x04, 0x9a, 0x59, 0x32, 0xbc, 0x44, - 0x1c, 0x46, 0x86, 0xe2, 0x0e, 0x41, 0xdc, 0x80, 0x30, 0x03, 0x36, 0x23, 0x9b, 0xc7, 0xf0, 0xae, - 0xb8, 0x25, 0xae, 0x04, 0xdd, 0x83, 0x62, 0x0c, 0x2e, 0x29, 0x29, 0xf3, 0x89, 0x05, 0xcc, 0x17, - 0x62, 0x85, 0xa7, 0xc9, 0xbd, 0x74, 0x39, 0x92, 0x51, 0xa0, 0x47, 0x87, 0x80, 0xb1, 0x04, 0x2f, - 0x7c, 0x02, 0xea, 0x8c, 0xa8, 0x67, 0xc0, 0xa4, 0x3b, 0x4c, 0xba, 0x4f, 0xe5, 0xdc, 0x75, 0xf8, - 0x86, 0x02, 0xef, 0x80, 0x00, 0x0c, 0x89, 0x44, 0x7a, 0xe4, 0x49, 0x15, 0x30, 0x18, 0xf3, 0x03, - 0x80, 0xbf, 0x93, 0x75, 0xe0, 0x06, 0xea, 0x46, 0x7c, 0x27, 0x8e, 0x04, 0xf2, 0x91, 0x0c, 0x95, - 0x71, 0x85, 0x61, 0xd2, 0x35, 0x74, 0x81, 0xee, 0x6b, 0xcf, 0xa1, 0x26, 0x43, 0x46, 0x3d, 0x70, - 0x09, 0xcc, 0x88, 0x29, 0xa7, 0xfe, 0xee, 0x25, 0xc0, 0x07, 0xf2, 0x95, 0x78, 0x85, 0x86, 0x94, - 0x4e, 0xf0, 0x23, 0x0f, 0xc7, 0xb5, 0xa4, 0x5c, 0x28, 0x0d, 0x58, 0xc0, 0x63, 0x7e, 0xa5, 0x2c, - 0x9b, 0x51, 0x1b, 0xd1, 0x73, 0x18, 0xd2, 0x73, 0xe8, 0x5f, 0xb9, 0x32, 0xec, 0xbf, 0xf6, 0xbc, - 0xf7, 0x84, 0xff, 0x15, 0x86, 0x1c, 0x31, 0xe5, 0x41, 0x78, 0x89, 0x67, 0x64, 0x88, 0x28, 0x1e, - 0xf3, 0x38, 0xf2, 0x99, 0xc9, 0xa0, 0xfb, 0x5f, 0x29, 0x7a, 0xb3, 0xca, 0xaa, 0xa5, 0xa1, 0x96, - 0xd6, 0x06, 0x97, 0x4a, 0x84, 0xa5, 0x48, 0x21, 0xdf, 0x2b, 0x25, 0xeb, 0xcb, 0x4a, 0xfa, 0x21, - 0x81, 0x57, 0x3a, 0x51, 0xd3, 0x15, 0xad, 0x3f, 0x57, 0x24, 0xf2, 0xcb, 0x4a, 0x03, 0x80, 0x1a, - 0xdc, 0x9a, 0x54, 0x8c, 0x37, 0xa0, 0x61, 0x34, 0x20, 0xf5, 0x1b, 0xb8, 0xa4, 0xb1, 0x84, 0x19, - 0x54, 0x31, 0xe4, 0x04, 0x69, 0x48, 0xcf, 0x2e, 0x3f, 0x53, 0xaa, 0x82, 0xe7, 0xab, 0xd2, 0x02, - 0x2e, 0xeb, 0x66, 0x81, 0x7c, 0x54, 0x5b, 0x4b, 0x65, 0x42, 0xda, 0xaa, 0xae, 0xb4, 0x9d, 0x5d, - 0x56, 0xa6, 0xa7, 0x8d, 0x51, 0x9a, 0x26, 0x2a, 0x43, 0x69, 0x3a, 0x43, 0x9a, 0xa3, 0xb8, 0x2c, - 0xe9, 0x0a, 0xaf, 0xa7, 0x6b, 0x2b, 0x5c, 0xc7, 0x80, 0xf8, 0x1c, 0x80, 0x16, 0x56, 0x55, 0xca, - 0x60, 0xf9, 0xc1, 0x53, 0x0f, 0x5c, 0x1e, 0xb2, 0x3a, 0xfa, 0x3c, 0x56, 0xc0, 0x46, 0x4a, 0x59, - 0x3d, 0xc3, 0xf4, 0x09, 0x19, 0x1a, 0x85, 0x67, 0x09, 0x1e, 0x4b, 0x59, 0xeb, 0xaa, 0x47, 0x00, - 0xae, 0x68, 0x5f, 0x34, 0xa0, 0x6c, 0x09, 0x57, 0xd6, 0xb4, 0xf7, 0x9e, 0x77, 0xc5, 0x55, 0x95, - 0x38, 0x69, 0x51, 0xa6, 0x21, 0xcb, 0xa1, 0x39, 0x7e, 0x3d, 0x7c, 0x3f, 0x7c, 0x4d, 0x1a, 0xef, - 0x99, 0xee, 0xf8, 0xa5, 0x6f, 0x72, 0x4a, 0x68, 0x82, 0x57, 0xc8, 0xbf, 0x6a, 0xaf, 0x54, 0xed, - 0xd7, 0xdf, 0x87, 0x87, 0xf5, 0xb0, 0xdf, 0xd0, 0xf4, 0x5f, 0x0f, 0x2f, 0xc1, 0xd4, 0x31, 0x6a, - 0x50, 0x0b, 0xa3, 0xf4, 0xcd, 0xe1, 0x7b, 0x40, 0xf6, 0x4c, 0x4e, 0x94, 0x4d, 0x44, 0x4e, 0xd3, - 0x73, 0x5f, 0x37, 0x4a, 0x3c, 0x17, 0x9d, 0xdf, 0x87, 0x57, 0xd4, 0xbd, 0xc2, 0x56, 0x2d, 0x87, - 0x35, 0x95, 0xcf, 0x1c, 0x90, 0x7f, 0x72, 0x4d, 0x66, 0x11, 0x6e, 0x24, 0x4c, 0xf0, 0xcd, 0x0c, - 0x6c, 0x9f, 0xb4, 0x3a, 0x34, 0x49, 0x0a, 0xfc, 0x20, 0x35, 0x9a, 0xea, 0xe8, 0x42, 0x96, 0x3c, - 0x32, 0xc9, 0xf8, 0x88, 0xc3, 0xbe, 0x89, 0x26, 0x3c, 0xcb, 0x19, 0x53, 0x19, 0x94, 0x17, 0x0a, - 0x41, 0xed, 0x48, 0x10, 0x00, 0xeb, 0xb2, 0x4a, 0x0c, 0xa8, 0x36, 0x94, 0x42, 0x07, 0x79, 0xb8, - 0xb0, 0xb6, 0x9a, 0x94, 0x61, 0x1b, 0xf2, 0xc9, 0xa1, 0x76, 0x54, 0x1b, 0xda, 0x21, 0x0d, 0xe1, - 0x9a, 0x4a, 0xab, 0x86, 0x26, 0xc9, 0xc9, 0x84, 0x44, 0xa0, 0x1e, 0x57, 0xa1, 0x09, 0xb3, 0x83, - 0x36, 0x98, 0x78, 0x79, 0x3f, 0x78, 0x03, 0x64, 0x25, 0x52, 0x3e, 0xe1, 0x49, 0x53, 0x32, 0xca, - 0x7e, 0x69, 0x22, 0x00, 0x38, 0x63, 0x52, 0x4c, 0x22, 0x83, 0x3c, 0x26, 0x8a, 0x6d, 0xb2, 0xb3, - 0x31, 0x91, 0x43, 0x16, 0x35, 0x92, 0x78, 0x8c, 0xa8, 0x07, 0xcc, 0x9c, 0x66, 0xbc, 0x04, 0x8a, - 0x74, 0x9b, 0x09, 0x1d, 0x5c, 0x31, 0x45, 0x83, 0x4b, 0x22, 0x96, 0xec, 0x8a, 0x68, 0x19, 0x18, - 0x7a, 0xc4, 0x8a, 0xbb, 0xaf, 0x1e, 0x44, 0xdb, 0xac, 0xed, 0xe1, 0x1c, 0x9a, 0x45, 0xb3, 0x4a, - 0xb8, 0x2f, 0xf2, 0x9a, 0x08, 0xb9, 0x34, 0xc9, 0x1b, 0x62, 0x26, 0xe3, 0xf2, 0xc4, 0x99, 0x3c, - 0xfa, 0x20, 0x48, 0xa0, 0xcf, 0x34, 0x89, 0x72, 0x82, 0x39, 0xe6, 0x8d, 0x34, 0x1d, 0x80, 0x9e, - 0x61, 0xf2, 0x30, 0xb6, 0x58, 0x31, 0xc1, 0xc0, 0x11, 0x7d, 0x71, 0x0b, 0x81, 0xd0, 0xe4, 0x85, - 0x90, 0x40, 0x6f, 0x4c, 0x6b, 0x49, 0x5f, 0x11, 0xf2, 0xb9, 0x90, 0xe7, 0x2f, 0xd0, 0x7f, 0xcc, - 0xf9, 0x03, 0xb4, 0x0d, 0x13, 0x8f, 0x2c, 0x9a, 0x2e, 0x73, 0x78, 0x4c, 0x8c, 0x07, 0xe6, 0x07, - 0x7a, 0x44, 0x9a, 0x79, 0x0d, 0x3e, 0xbf, 0xf1, 0xc8, 0x8b, 0x02, 0x7a, 0x30, 0xc7, 0x94, 0x6a, - 0x4c, 0x23, 0xdb, 0x34, 0x67, 0xb7, 0x1d, 0x8f, 0xa7, 0x30, 0x03, 0x97, 0xe6, 0xf3, 0x34, 0x25, - 0x1a, 0x87, 0x97, 0x8c, 0x62, 0xa8, 0xa6, 0x95, 0x64, 0xd8, 0x14, 0xde, 0x78, 0x72, 0x66, 0xd0, - 0x14, 0x8e, 0x2c, 0x09, 0xbe, 0x00, 0x8d, 0x55, 0xd4, 0x98, 0xbb, 0x72, 0x56, 0x4b, 0x73, 0x45, - 0x80, 0x25, 0x4f, 0x05, 0x82, 0x47, 0x5e, 0x42, 0x21, 0x91, 0xba, 0x78, 0x73, 0x39, 0x26, 0x8f, - 0x27, 0xef, 0x34, 0xd9, 0x34, 0x14, 0x1a, 0x92, 0x0f, 0x84, 0x89, 0x45, 0x15, 0x88, 0xdd, 0xb0, - 0xe8, 0x12, 0x57, 0x4b, 0x55, 0xfb, 0xea, 0x01, 0x71, 0xd7, 0xf9, 0xfc, 0x46, 0xc6, 0xe0, 0xe1, - 0xdc, 0x92, 0x5c, 0xb7, 0x86, 0x16, 0x71, 0x1d, 0x37, 0xca, 0xd0, 0x80, 0x35, 0xf1, 0x11, 0x68, - 0x49, 0xc6, 0xba, 0x83, 0xc4, 0xe5, 0x55, 0x06, 0x5c, 0x00, 0xd3, 0x61, 0x2e, 0x83, 0x48, 0x4c, - 0xdc, 0xf9, 0xc6, 0x4b, 0x0f, 0x2e, 0x7b, 0x10, 0x72, 0xb2, 0x3e, 0xff, 0xb1, 0x3d, 0xc6, 0x70, - 0xc4, 0xed, 0x69, 0x02, 0xeb, 0xc0, 0xc8, 0x80, 0x1a, 0x59, 0xcf, 0x9c, 0x96, 0x36, 0x10, 0x3a, - 0xe8, 0x8b, 0x63, 0x28, 0x39, 0x0f, 0x61, 0x0f, 0x3f, 0xaf, 0x99, 0x03, 0xa8, 0xf0, 0xd1, 0xc0, - 0x1d, 0x12, 0xb2, 0x24, 0xb1, 0xa1, 0xa5, 0x04, 0x1c, 0xf0, 0x84, 0x7f, 0x90, 0x78, 0x72, 0xed, - 0x20, 0x18, 0x7c, 0x2e, 0x55, 0xea, 0xc7, 0xb4, 0xa5, 0x54, 0xb0, 0xee, 0x95, 0x37, 0xb8, 0xf3, - 0x06, 0xaf, 0x9d, 0xf7, 0xce, 0x67, 0xb5, 0x20, 0xd9, 0xa3, 0x15, 0xc9, 0x7a, 0x2e, 0x48, 0x7c, - 0xa0, 0x58, 0x4b, 0x0b, 0x1f, 0x4a, 0x3a, 0x21, 0x47, 0x47, 0x48, 0x66, 0x4e, 0x8b, 0x02, 0x24, - 0x8c, 0xb1, 0x41, 0xe2, 0x84, 0x29, 0x52, 0x6a, 0x3a, 0xcc, 0xa1, 0x39, 0x21, 0x54, 0x87, 0x14, - 0x8b, 0x92, 0xaf, 0x21, 0x69, 0x55, 0xe8, 0x5b, 0xd4, 0xd0, 0xa2, 0xec, 0x0e, 0x78, 0x73, 0xb9, - 0x64, 0x72, 0xd8, 0xc1, 0xe2, 0x5c, 0x3e, 0x18, 0xc4, 0xed, 0x4a, 0xdd, 0x2d, 0xf9, 0x40, 0x65, - 0xc8, 0xe0, 0xac, 0x11, 0xc1, 0x0d, 0xa8, 0xa3, 0xcf, 0x6c, 0xc5, 0xcd, 0xcf, 0x6b, 0xfc, 0xf5, - 0x2d, 0xf9, 0x62, 0xc9, 0x07, 0x8b, 0x1e, 0xfc, 0xcf, 0x7a, 0xaa, 0x7a, 0x59, 0x2e, 0xdd, 0x69, - 0xa6, 0xf0, 0xb9, 0xc9, 0xec, 0x36, 0x11, 0xb3, 0x9e, 0xb8, 0x13, 0x9b, 0x74, 0xb1, 0xa0, 0x63, - 0x66, 0xf1, 0xb6, 0x5d, 0xc6, 0x5c, 0x81, 0x73, 0x70, 0x42, 0x9a, 0x54, 0xd3, 0xcd, 0x25, 0xb7, - 0xe7, 0x8c, 0x43, 0x16, 0xaf, 0x1b, 0x0c, 0x39, 0x52, 0xf3, 0x3b, 0x5c, 0xca, 0xc8, 0x1f, 0x50, - 0x38, 0x54, 0x1d, 0xe0, 0xd9, 0xc6, 0xde, 0x68, 0xcc, 0x21, 0x03, 0x4d, 0x03, 0xc3, 0x72, 0xb8, - 0xa5, 0xef, 0xca, 0x30, 0x87, 0xd6, 0xad, 0x22, 0xb4, 0x1f, 0x97, 0xdd, 0xae, 0x42, 0x8a, 0xeb, - 0xa3, 0x61, 0x48, 0x21, 0x9d, 0x87, 0xae, 0x41, 0x54, 0x63, 0xd7, 0xba, 0x97, 0xc3, 0x37, 0xca, - 0x64, 0xfb, 0xaa, 0xe3, 0x23, 0x1d, 0x34, 0xdc, 0xb2, 0xa3, 0x1a, 0xf9, 0x4a, 0x61, 0x62, 0x84, - 0x57, 0x55, 0x95, 0xc4, 0xf7, 0xf2, 0x11, 0xaa, 0x14, 0xed, 0x55, 0x37, 0xc9, 0x9d, 0xcb, 0x8a, - 0x5d, 0x47, 0xf8, 0xa9, 0x89, 0x56, 0x1d, 0xae, 0xc8, 0xc7, 0x0e, 0xdc, 0x81, 0xcc, 0x3a, 0x99, - 0x53, 0x1a, 0x94, 0x1e, 0xb6, 0xec, 0xa9, 0xc6, 0xac, 0xbd, 0x4b, 0x09, 0xea, 0xf6, 0xc7, 0xda, - 0x69, 0x38, 0xba, 0xbd, 0x1c, 0xe7, 0x4a, 0x8d, 0x0b, 0xe2, 0x5b, 0xba, 0xf0, 0x57, 0x6d, 0x4a, - 0xd7, 0x49, 0x44, 0x3b, 0xb6, 0xd0, 0xb7, 0xe9, 0x5d, 0x94, 0xd1, 0x79, 0xa4, 0x38, 0xdd, 0xe4, - 0xb3, 0xdd, 0xde, 0xfc, 0x6a, 0xb6, 0xbc, 0xdd, 0xf0, 0x59, 0xdf, 0x33, 0xd1, 0xdf, 0x65, 0xa2, - 0xb8, 0xcd, 0x36, 0xc6, 0x22, 0x9d, 0xdf, 0xae, 0xc5, 0xa6, 0xb0, 0x6f, 0x44, 0xf1, 0x2a, 0x11, - 0xf4, 0xf8, 0xc7, 0x87, 0x1f, 0x16, 0x68, 0xb1, 0x9f, 0xea, 0xe6, 0x06, 0x1d, 0x67, 0x78, 0x1d, - 0x2f, 0x84, 0x3e, 0x32, 0x72, 0xd6, 0xdf, 0x11, 0x6c, 0x31, 0xfb, 0xea, 0xac, 0xda, 0x73, 0xef, - 0x4f, 0xe9, 0xe8, 0x59, 0x63, 0x59, 0xba, 0xa7, 0xe2, 0xf5, 0x17, 0x3d, 0xb3, 0x47, 0x47, 0x85, - 0x5e, 0xbd, 0x7b, 0x6b, 0xa8, 0x3d, 0x32, 0xb1, 0xb0, 0x8d, 0xb7, 0x09, 0x7d, 0x99, 0x68, 0xdc, - 0x47, 0x71, 0x61, 0x44, 0x46, 0x12, 0x17, 0x45, 0x22, 0xf8, 0x34, 0x6b, 0xb1, 0x12, 0x1b, 0x3a, - 0xce, 0x46, 0x27, 0x24, 0x8b, 0x55, 0x9c, 0x1b, 0x5b, 0x40, 0xb3, 0x09, 0x42, 0xaf, 0x6f, 0x56, - 0x23, 0xce, 0x66, 0x33, 0x61, 0xd3, 0xc6, 0xf5, 0xb7, 0x67, 0xf2, 0x3e, 0xeb, 0xd1, 0xa9, 0x9c, - 0x9e, 0x09, 0xb4, 0xca, 0x23, 0x24, 0xbd, 0xbe, 0xcd, 0x6b, 0xe8, 0x57, 0x71, 0x5e, 0xd8, 0x99, - 0x58, 0xa7, 0x77, 0xc0, 0xab, 0x76, 0xde, 0xa4, 0x4f, 0xad, 0xcb, 0x13, 0x1a, 0x8d, 0xd6, 0xd1, - 0x62, 0xd1, 0x6c, 0xda, 0x9f, 0x94, 0x03, 0x95, 0x48, 0x1c, 0x1f, 0xec, 0xa0, 0xfb, 0xf1, 0x91, - 0xba, 0xf0, 0xea, 0xef, 0x4b, 0xfe, 0x43, 0x36, 0xb4, 0xe7, 0x4c, 0x4d, 0xc1, 0x7a, 0x40, 0x91, - 0x1b, 0x5c, 0x9d, 0x20, 0x78, 0x37, 0xa2, 0x3f, 0x95, 0xf2, 0xd9, 0x88, 0x7b, 0xe3, 0xcf, 0x7f, - 0xba, 0x3a, 0xfb, 0x1b, 0x9d, 0x04, 0x9c, 0x9c, 0x9f, 0x7f, 0xb5, 0xbb, 0x8f, 0x37, 0x8b, 0xf4, - 0xde, 0x4e, 0xd2, 0x39, 0xef, 0xc0, 0xd9, 0xab, 0x34, 0x2f, 0x68, 0x53, 0x77, 0x7f, 0x4e, 0xbb, - 0xe5, 0x7f, 0xeb, 0x4f, 0x97, 0xf4, 0x4d, 0x14, 0xc4, 0x6f, 0x93, 0x10, 0xce, 0xce, 0xc4, 0xec, - 0x42, 0xd8, 0x7f, 0xcf, 0xa1, 0x33, 0xfd, 0x7e, 0xad, 0x6c, 0x47, 0x47, 0xc6, 0xfe, 0x12, 0x2f, - 0xe3, 0x1f, 0xd5, 0x36, 0x38, 0x7a, 0x98, 0xdd, 0x88, 0x31, 0x1b, 0x24, 0x56, 0xfb, 0x3a, 0x51, - 0xf2, 0x23, 0x50, 0x82, 0x41, 0xea, 0x58, 0x64, 0x0f, 0x44, 0x98, 0x2c, 0xb4, 0x7a, 0xcf, 0xc1, - 0x67, 0x3e, 0xdc, 0x68, 0xcb, 0x2f, 0xc0, 0x7f, 0x4c, 0x17, 0xc2, 0x8e, 0x17, 0x80, 0x2b, 0x4f, - 0x22, 0xcc, 0xbe, 0x70, 0xf6, 0xa0, 0x00, 0x98, 0x16, 0xc4, 0x90, 0xb2, 0x75, 0xab, 0x09, 0x41, - 0xa4, 0x63, 0x57, 0x7d, 0xfb, 0x2e, 0x4a, 0x6e, 0xc5, 0x8c, 0x94, 0xc9, 0x9e, 0x8b, 0x24, 0xc9, - 0x7f, 0x71, 0x3f, 0xd8, 0x31, 0x66, 0x32, 0xd9, 0xeb, 0x9f, 0xdf, 0x5c, 0x99, 0xaa, 0x1d, 0x6f, - 0x6f, 0xa3, 0x71, 0x59, 0x71, 0xaa, 0x43, 0xa5, 0xf8, 0x36, 0x7f, 0xc8, 0x7a, 0x56, 0xa3, 0xad, - 0x83, 0x3b, 0x3b, 0xb9, 0xe6, 0x59, 0xcc, 0x4a, 0x8b, 0xfb, 0xef, 0x5b, 0x91, 0x3d, 0xbc, 0x63, - 0x82, 0xd3, 0xec, 0xac, 0xf7, 0x65, 0x79, 0x14, 0x0f, 0xe2, 0x2b, 0x6a, 0x38, 0xf4, 0x7a, 0xa6, - 0xa0, 0x73, 0xd7, 0xaf, 0x22, 0x90, 0x0b, 0xee, 0x9b, 0x79, 0x1f, 0x02, 0x20, 0x01, 0x47, 0x15, - 0xb0, 0x79, 0x26, 0xa2, 0x42, 0x28, 0x0b, 0x3e, 0xeb, 0x15, 0x90, 0x81, 0xb9, 0x51, 0xe7, 0x61, - 0x7b, 0xcf, 0xf3, 0x69, 0x64, 0xd3, 0x21, 0x61, 0x33, 0x22, 0x71, 0xbc, 0x42, 0x4c, 0x29, 0xae, - 0xf8, 0xe0, 0x87, 0xc0, 0xc0, 0xbc, 0xa9, 0xd4, 0x33, 0x2b, 0x79, 0xf4, 0xd1, 0xac, 0x1a, 0xfe, - 0x6f, 0x2f, 0x8a, 0xc5, 0x45, 0xfd, 0xb0, 0x4f, 0x8f, 0xbe, 0x51, 0x49, 0xd5, 0x2f, 0x04, 0x29, - 0x89, 0xa9, 0x23, 0x6e, 0x52, 0x7a, 0x5f, 0xed, 0x36, 0x7b, 0xda, 0x12, 0x46, 0xbf, 0xbf, 0xd5, - 0x41, 0x3d, 0x67, 0x58, 0xe5, 0x61, 0x38, 0xd5, 0xee, 0xab, 0x9d, 0xb0, 0xe9, 0x75, 0xdf, 0xd5, - 0xe1, 0x19, 0x75, 0x50, 0x7b, 0x60, 0xe5, 0x69, 0xf8, 0xde, 0xc5, 0x33, 0xe8, 0x07, 0x7d, 0xbe, - 0xb7, 0xb9, 0x29, 0x56, 0xcf, 0x11, 0x1b, 0xff, 0xb8, 0xe6, 0xce, 0xc4, 0xa8, 0x5c, 0xc0, 0x82, - 0xe2, 0xe2, 0xe1, 0xdb, 0x06, 0x9c, 0x1e, 0x11, 0x01, 0x3e, 0xc8, 0xc5, 0xe2, 0xe7, 0x3d, 0xd9, - 0x7c, 0x72, 0xa4, 0x8d, 0x5c, 0xf0, 0xd3, 0xad, 0x4c, 0xe8, 0xf0, 0x16, 0xae, 0x6d, 0x71, 0xb9, - 0x8a, 0x93, 0xc5, 0x59, 0x44, 0x6a, 0x4c, 0x0a, 0x50, 0x9d, 0xca, 0x3c, 0x61, 0x88, 0x0d, 0x23, - 0x7e, 0x4b, 0x1b, 0xf2, 0xa2, 0x10, 0x59, 0xfe, 0xfb, 0x99, 0xb1, 0xdc, 0x60, 0x67, 0x93, 0x7d, - 0xba, 0x35, 0xff, 0xc4, 0x9f, 0xbf, 0xd8, 0x1f, 0xc5, 0x03, 0xa9, 0x6a, 0xa5, 0x6c, 0x65, 0xc0, - 0x80, 0x95, 0x15, 0x36, 0x3b, 0xee, 0xfc, 0x2f, 0x71, 0xb1, 0x3a, 0x93, 0x87, 0xe2, 0xa5, 0xb9, - 0x7c, 0xf3, 0xcd, 0x19, 0x68, 0x29, 0x0f, 0xa0, 0x37, 0xec, 0x47, 0xfc, 0x52, 0x7c, 0x30, 0x17, - 0x82, 0x8e, 0x6f, 0x19, 0xf4, 0xdc, 0x37, 0x3b, 0xc0, 0x80, 0xe3, 0x1a, 0x8a, 0x3e, 0x2f, 0xff, - 0x08, 0x90, 0xa7, 0x78, 0x1a, 0x93, 0x4c, 0xa9, 0xc6, 0x71, 0x1d, 0x09, 0xe1, 0xa8, 0xd4, 0xe3, - 0x2f, 0xd5, 0xd1, 0x7e, 0x4b, 0x7e, 0xad, 0xd4, 0xfb, 0x00, 0x34, 0xf4, 0x6e, 0x67, 0x4f, 0xfa, - 0xf6, 0x2e, 0x8c, 0x9e, 0xbd, 0x88, 0xd7, 0xfa, 0x5c, 0x1e, 0x1f, 0xba, 0xcf, 0xb3, 0xf9, 0xac, - 0xf7, 0xec, 0xf9, 0x09, 0xc0, 0xcf, 0x9f, 0x71, 0x0e, 0xd8, 0x84, 0x98, 0x8b, 0xe2, 0x65, 0x51, - 0x64, 0xf1, 0xf5, 0x6d, 0x01, 0x99, 0xf3, 0xd6, 0x38, 0x42, 0x65, 0x4f, 0x11, 0xa8, 0x3f, 0x3b, - 0x38, 0x68, 0x07, 0x2b, 0x44, 0x33, 0xf9, 0x6b, 0x06, 0x14, 0x28, 0xea, 0x6e, 0x55, 0x3a, 0x82, - 0x1f, 0x79, 0x59, 0x1a, 0xbe, 0xa2, 0x90, 0xa1, 0x3a, 0x3f, 0xea, 0x29, 0x16, 0xf1, 0x1d, 0xf4, - 0x2c, 0x6f, 0x0d, 0x01, 0x9f, 0x69, 0xf6, 0x24, 0x35, 0x7c, 0x9c, 0xf9, 0x39, 0xb8, 0x96, 0xb7, - 0x59, 0x3d, 0x2f, 0x36, 0xb2, 0x15, 0x37, 0x31, 0xeb, 0x3a, 0x7b, 0xdc, 0x33, 0xad, 0x3c, 0x34, - 0x89, 0x0e, 0xa4, 0xa6, 0x4f, 0x45, 0xf7, 0x9a, 0xce, 0xa7, 0xc0, 0xa8, 0x4d, 0xe3, 0x63, 0xf0, - 0x9b, 0xa3, 0xe0, 0xe9, 0x18, 0x1f, 0x06, 0xd8, 0xb4, 0x07, 0x90, 0xe5, 0x2d, 0x68, 0x1b, 0x66, - 0xb4, 0xfe, 0x94, 0x04, 0x7c, 0xae, 0x57, 0xe6, 0x72, 0xa8, 0xf8, 0xe8, 0x50, 0x11, 0xc6, 0x51, - 0x59, 0x54, 0xdc, 0xc5, 0x3e, 0xfa, 0x68, 0x01, 0xcc, 0x61, 0xde, 0xb5, 0x1b, 0xe8, 0x2f, 0x16, - 0x0e, 0xb9, 0x1c, 0xb7, 0x31, 0x97, 0xc7, 0xee, 0x7b, 0x54, 0x53, 0xe7, 0x4b, 0x7c, 0xc2, 0x93, - 0xf3, 0xe9, 0xbb, 0xb7, 0xc8, 0x99, 0x98, 0xbe, 0xf2, 0x13, 0x8b, 0x26, 0x7d, 0x70, 0xf3, 0x9b, - 0x66, 0xc4, 0xaa, 0x19, 0x8b, 0x90, 0x6a, 0x03, 0xf6, 0x4f, 0x9b, 0xbe, 0xe1, 0x17, 0xe7, 0x43, - 0xc3, 0x80, 0xf9, 0x8c, 0x91, 0xe4, 0xde, 0x3f, 0xfe, 0x01, 0x5f, 0xb2, 0xab, 0x4a, 0xdc, 0xde, - 0xa4, 0xf7, 0x93, 0x34, 0x88, 0x9e, 0x69, 0xdb, 0xb6, 0xd8, 0x9b, 0x35, 0x1b, 0x54, 0x60, 0x81, - 0x7f, 0x16, 0x8b, 0xa6, 0xd7, 0x39, 0xfb, 0x45, 0x98, 0xd1, 0x07, 0x73, 0x43, 0x61, 0x2e, 0x5e, - 0x9e, 0x89, 0xc6, 0x80, 0x35, 0x3f, 0xd3, 0x3f, 0xea, 0x76, 0xa2, 0xa9, 0x48, 0x90, 0x59, 0xa2, - 0xf3, 0x17, 0xe2, 0xd0, 0xdf, 0x48, 0xa3, 0xea, 0x1f, 0x80, 0xae, 0xd1, 0xd2, 0xcf, 0x67, 0x0d, - 0x43, 0x42, 0xe4, 0xec, 0x33, 0xcc, 0x43, 0x84, 0xb2, 0xe8, 0xde, 0x9a, 0x53, 0x3e, 0x27, 0x59, - 0x76, 0x5c, 0x5f, 0xf8, 0x13, 0x88, 0xba, 0xce, 0xd4, 0xf0, 0xb5, 0xc1, 0x85, 0xf5, 0x59, 0xdf, - 0xbc, 0x4b, 0xe3, 0x45, 0x95, 0x93, 0xd3, 0x19, 0x96, 0x96, 0xcc, 0xf6, 0x9d, 0xe3, 0xff, 0x3d, - 0xba, 0x8b, 0xe4, 0x59, 0x0d, 0x8d, 0x46, 0x7a, 0x1c, 0x0d, 0xd5, 0x4e, 0xe3, 0x91, 0xfe, 0x13, - 0x78, 0xa4, 0x47, 0xf0, 0xa0, 0xdf, 0x14, 0x02, 0x06, 0x74, 0xab, 0x60, 0x9d, 0x15, 0xa7, 0x9d, - 0x4f, 0xdb, 0xbd, 0xb1, 0xf1, 0x64, 0xe9, 0x7d, 0xef, 0xf9, 0x46, 0x86, 0x0b, 0xb0, 0xcd, 0x96, - 0x87, 0x4e, 0x7a, 0xf4, 0x01, 0x19, 0x05, 0xe4, 0x0a, 0x65, 0x1a, 0xab, 0x65, 0xd6, 0x85, 0x12, - 0x15, 0x02, 0x06, 0x3c, 0x45, 0x64, 0x1e, 0x17, 0x09, 0x9f, 0x05, 0x04, 0x2b, 0x40, 0xcc, 0x09, - 0x2c, 0x39, 0xf7, 0xe9, 0xc6, 0x53, 0x30, 0x86, 0x5d, 0xde, 0x99, 0x67, 0x22, 0x98, 0xad, 0x5c, - 0xa7, 0x29, 0xa6, 0x39, 0x1b, 0x4c, 0x56, 0xa8, 0x22, 0x5d, 0x1a, 0x1b, 0x0e, 0xa5, 0x5d, 0x5d, - 0xf4, 0xf1, 0xdb, 0x1e, 0x01, 0x6d, 0x79, 0x01, 0x7d, 0x14, 0x57, 0xfa, 0x5b, 0x85, 0x11, 0x35, - 0x53, 0xc9, 0xee, 0xe6, 0xd0, 0x71, 0xd4, 0x0e, 0xfb, 0x13, 0x3e, 0xf2, 0x90, 0x64, 0x7f, 0x4a, - 0x5c, 0x39, 0xee, 0x9e, 0x65, 0x38, 0x38, 0xf0, 0xcf, 0x8d, 0x73, 0xbd, 0x0a, 0xc8, 0x09, 0x15, - 0xdb, 0x82, 0x60, 0xcc, 0x07, 0x8f, 0x40, 0x51, 0x5c, 0x37, 0x53, 0x9b, 0x98, 0x74, 0xa9, 0x7e, - 0x96, 0x52, 0x90, 0x4b, 0x6b, 0x48, 0xb1, 0x55, 0x10, 0xb5, 0x0b, 0xd2, 0xb6, 0x3f, 0xa7, 0xcc, - 0x75, 0xb1, 0xf8, 0x81, 0xe8, 0x2e, 0x9d, 0x62, 0xd1, 0xdf, 0x6b, 0xbb, 0x2d, 0xd4, 0x2c, 0x60, - 0x73, 0xc8, 0xde, 0x3a, 0x53, 0xdb, 0xbe, 0x9a, 0xd1, 0xb5, 0xe0, 0x9d, 0x58, 0xdc, 0x27, 0xd9, - 0x4c, 0xd5, 0x4d, 0x9a, 0x74, 0x94, 0xae, 0xc4, 0xff, 0xcd, 0x37, 0x47, 0xc4, 0xaf, 0xe3, 0x39, - 0x44, 0xcc, 0xbe, 0xb1, 0xae, 0x32, 0xc0, 0x7e, 0x23, 0xb1, 0xcf, 0xfb, 0x27, 0x34, 0x55, 0x25, - 0xe3, 0xc7, 0x54, 0x55, 0x83, 0xa8, 0x5c, 0xad, 0x50, 0x33, 0x89, 0xe3, 0xf9, 0x81, 0x74, 0xd9, - 0x9c, 0x22, 0x34, 0x29, 0xcb, 0x15, 0x37, 0x45, 0x2b, 0x3f, 0xce, 0x39, 0xf9, 0x2a, 0x79, 0x6d, - 0x4b, 0x9c, 0xc4, 0xe2, 0x88, 0x91, 0xd2, 0xe8, 0x8b, 0xd9, 0x9b, 0xa8, 0x58, 0xd9, 0xfc, 0xd9, - 0xae, 0xa6, 0xf3, 0x3f, 0xce, 0xdc, 0x73, 0x74, 0x2e, 0xc4, 0xb6, 0xdf, 0x3f, 0xaf, 0x9e, 0xa7, - 0x8f, 0x31, 0xaf, 0x5d, 0x4f, 0xbd, 0x7a, 0xa6, 0xea, 0x7d, 0x50, 0xbb, 0x8e, 0x37, 0x54, 0x89, - 0x5b, 0x47, 0x5d, 0xf4, 0x89, 0xeb, 0xa2, 0x4f, 0x15, 0x39, 0x3f, 0xf2, 0x30, 0x67, 0x98, 0x65, - 0x16, 0xe9, 0xf7, 0xf1, 0x27, 0xb1, 0x38, 0xf3, 0xfb, 0xfb, 0x0e, 0x9d, 0xe3, 0xd4, 0x21, 0x7b, - 0xc4, 0xca, 0xb2, 0x03, 0xfb, 0x28, 0xbf, 0xee, 0x01, 0x21, 0x59, 0x5b, 0xb5, 0xb3, 0xb6, 0x79, - 0x34, 0x19, 0x9a, 0xf5, 0xf7, 0x7b, 0x81, 0x78, 0xba, 0x50, 0xfe, 0x58, 0x67, 0x9e, 0x7d, 0x52, - 0xb8, 0xee, 0x24, 0xb9, 0x91, 0x38, 0x1e, 0x50, 0x81, 0x1c, 0x40, 0xb3, 0xf5, 0x8b, 0x72, 0xa5, - 0x45, 0xfa, 0xb5, 0xda, 0x7b, 0xe9, 0xb4, 0x6a, 0x65, 0x6a, 0x1e, 0x48, 0x8b, 0xba, 0x65, 0xe9, - 0x3f, 0xfe, 0x21, 0xba, 0x32, 0x96, 0x55, 0xb4, 0xb9, 0x81, 0xfc, 0x58, 0x11, 0x75, 0xf6, 0x5c, - 0x9b, 0xcd, 0x7f, 0x28, 0xd5, 0x67, 0x56, 0x96, 0xb2, 0x24, 0x80, 0xfa, 0xe4, 0x24, 0xc0, 0xb3, - 0x7e, 0x03, 0x22, 0x40, 0x01, 0x82, 0xf2, 0x96, 0xff, 0x5c, 0xe7, 0x5f, 0x31, 0x2e, 0x07, 0xc7, - 0x9b, 0x43, 0x3d, 0x54, 0xc1, 0xb9, 0x98, 0xed, 0xf6, 0x53, 0xad, 0x52, 0x35, 0xd5, 0x17, 0x95, - 0xea, 0x8b, 0x9a, 0xea, 0x8b, 0x4a, 0x79, 0x71, 0x9f, 0x75, 0x43, 0x46, 0x2d, 0xb4, 0xf8, 0xa0, - 0x92, 0x14, 0x9c, 0xeb, 0xa2, 0x4f, 0x87, 0x75, 0x11, 0x85, 0x9a, 0x26, 0x99, 0x05, 0x7b, 0x4b, - 0xa3, 0x59, 0xb8, 0xa5, 0x5f, 0x1d, 0xfe, 0x01, 0x8a, 0xab, 0x10, 0x6c, 0x2d, 0xe4, 0x44, 0x77, - 0xa2, 0x31, 0xb3, 0xad, 0x26, 0xad, 0x7f, 0x4c, 0xd2, 0xeb, 0xb3, 0x5f, 0xfe, 0xcf, 0xbb, 0x9f, - 0x7e, 0xa4, 0xe9, 0x3a, 0x12, 0xfc, 0x78, 0xf9, 0xa0, 0x27, 0x62, 0xe6, 0xe6, 0x36, 0x49, 0x4c, - 0xaf, 0xff, 0xc1, 0xdc, 0x91, 0x7e, 0x4c, 0x7a, 0x50, 0x66, 0xe4, 0xaf, 0x3c, 0x9f, 0x3d, 0xa7, - 0x39, 0x6a, 0x6f, 0x0f, 0xc4, 0x19, 0xcc, 0xf7, 0x48, 0xde, 0xbf, 0x43, 0xc6, 0x3c, 0xd5, 0x9e, - 0x46, 0x26, 0xd0, 0xf0, 0x69, 0x66, 0xaf, 0x3e, 0xe1, 0x05, 0x35, 0x72, 0xc2, 0xdb, 0xe3, 0xef, - 0x72, 0x7b, 0xe6, 0x0e, 0x38, 0xad, 0xd2, 0xc5, 0xa4, 0xf7, 0xf6, 0xa7, 0x77, 0x3f, 0xf7, 0x4c, - 0xca, 0x63, 0x26, 0xc5, 0xbe, 0x31, 0x1b, 0x26, 0x7d, 0x6e, 0xcd, 0x86, 0x0f, 0xd7, 0x31, 0xf9, - 0xe8, 0x7a, 0xaa, 0x73, 0xd9, 0xde, 0x3b, 0x51, 0x14, 0x20, 0x26, 0x67, 0xd2, 0x17, 0x46, 0x7e, - 0x3b, 0x9f, 0xa3, 0xe5, 0x12, 0xf4, 0x3c, 0x18, 0x60, 0xc8, 0x12, 0xc6, 0xb6, 0x32, 0xd6, 0x98, - 0xc9, 0x67, 0x0f, 0x5f, 0xd0, 0xaa, 0xa5, 0x5c, 0xb9, 0x24, 0xb7, 0xa8, 0xd1, 0xa3, 0x8e, 0xbd, - 0xc7, 0xf0, 0x40, 0x07, 0x5b, 0x2e, 0x72, 0xe9, 0xd7, 0x8a, 0xe9, 0x8b, 0x54, 0x6d, 0xc4, 0xd3, - 0xec, 0xbc, 0xce, 0xf2, 0x92, 0x57, 0xa2, 0xe4, 0x15, 0x2f, 0x81, 0x99, 0xad, 0xb5, 0xb0, 0xbe, - 0x59, 0x35, 0x68, 0x2c, 0x66, 0xd6, 0xd6, 0xb5, 0x0e, 0x1b, 0x96, 0x1f, 0x0c, 0xc9, 0xa6, 0xd5, - 0x6b, 0xb9, 0xec, 0x26, 0x5d, 0x1f, 0x34, 0xbc, 0x83, 0xf5, 0xc2, 0xcc, 0x84, 0xfc, 0xc1, 0x89, - 0x09, 0x26, 0x64, 0x49, 0x82, 0x1c, 0x6f, 0x3f, 0x7d, 0xca, 0x3a, 0x48, 0xc9, 0x37, 0xf5, 0xb9, - 0x0b, 0x52, 0x40, 0xcd, 0xa8, 0x8e, 0x35, 0x6d, 0x5a, 0x25, 0xb9, 0x4c, 0x17, 0x08, 0x4d, 0x94, - 0xa0, 0x16, 0xb7, 0xb9, 0xa9, 0xd9, 0xbb, 0xef, 0x77, 0x75, 0xf3, 0x1c, 0x67, 0x36, 0x9b, 0xe9, - 0x5e, 0xdf, 0x1e, 0x8a, 0x5f, 0xb1, 0x5a, 0x50, 0x62, 0x4a, 0x1f, 0xd4, 0xff, 0xfc, 0xc3, 0x7f, - 0x1a, 0xf7, 0x71, 0x92, 0xe8, 0xc5, 0x6c, 0x63, 0x93, 0xde, 0xf3, 0xb7, 0xb0, 0xc6, 0x7f, 0xd1, - 0xc7, 0x6e, 0x24, 0x86, 0x1f, 0xde, 0x1a, 0x71, 0x6e, 0xd0, 0x8c, 0x6e, 0x72, 0x08, 0xef, 0x55, - 0x96, 0xa5, 0x59, 0xb9, 0x28, 0x4e, 0x2f, 0xa4, 0x36, 0xf3, 0x52, 0xa0, 0x13, 0x00, 0xbb, 0x40, - 0x5f, 0x5a, 0x81, 0xba, 0xbe, 0xa8, 0x34, 0xe8, 0xd7, 0xae, 0xb0, 0x96, 0xf3, 0x40, 0xa2, 0x12, - 0x3e, 0xe9, 0x2b, 0x4a, 0xc1, 0xf8, 0x9b, 0xfc, 0x4e, 0x5e, 0x57, 0xbf, 0x52, 0x81, 0xa1, 0xba, - 0x97, 0x29, 0x5f, 0x26, 0x09, 0x4f, 0x7c, 0x9b, 0x19, 0x84, 0xe8, 0x00, 0xa6, 0xbe, 0xcd, 0x67, - 0xad, 0x2f, 0x5d, 0x77, 0x7b, 0x6a, 0xab, 0xda, 0x9c, 0x1a, 0xcc, 0xd6, 0xeb, 0x0b, 0x27, 0xc6, - 0x6c, 0x2d, 0xfc, 0xd4, 0xd6, 0x83, 0x6f, 0xba, 0x67, 0xdd, 0xfd, 0x13, 0xaa, 0xd6, 0xd3, 0x3f, - 0x36, 0x80, 0xd8, 0x55, 0x5f, 0x57, 0x56, 0x9e, 0xbb, 0x15, 0xd2, 0xbf, 0x53, 0xaf, 0xdf, 0x67, - 0xd1, 0x0d, 0xc7, 0xf6, 0xfe, 0xb4, 0x99, 0x0e, 0x81, 0xe7, 0xea, 0xc3, 0xa6, 0xde, 0x53, 0x51, - 0x6b, 0x85, 0xf9, 0x3a, 0x84, 0xe3, 0xeb, 0x8c, 0xec, 0xb6, 0x8f, 0x34, 0xad, 0xf3, 0xa7, 0xb1, - 0xa9, 0x43, 0xc7, 0x6f, 0xe5, 0x52, 0x64, 0x97, 0x5e, 0x70, 0xb7, 0xba, 0x52, 0xec, 0x89, 0x05, - 0xfc, 0xf5, 0xc1, 0x65, 0x94, 0x24, 0xf4, 0x53, 0x2b, 0xd5, 0x96, 0x52, 0x7f, 0x57, 0xdb, 0x30, - 0x3a, 0x50, 0x79, 0x24, 0x89, 0x66, 0xce, 0x03, 0x35, 0xbe, 0x03, 0x69, 0x2e, 0xf3, 0x99, 0xb5, - 0x6a, 0xf2, 0x17, 0xcd, 0x95, 0x78, 0xae, 0xad, 0x7f, 0xaf, 0x83, 0x6a, 0x1a, 0x67, 0xf6, 0x85, - 0xd3, 0x5a, 0xc5, 0x91, 0x33, 0x46, 0xf9, 0x63, 0x72, 0xb4, 0x21, 0x76, 0x9b, 0x9d, 0xf9, 0xdb, - 0x4f, 0xfd, 0x9e, 0x9c, 0xd5, 0x3a, 0x48, 0x49, 0xf2, 0x6f, 0xcf, 0x9a, 0x64, 0xe4, 0x04, 0x42, - 0x7f, 0xdc, 0x71, 0x82, 0xcd, 0xfd, 0xc9, 0xb1, 0x76, 0x9d, 0x3c, 0x3e, 0xfc, 0x52, 0x43, 0x48, - 0x26, 0x74, 0xd2, 0xe1, 0x9e, 0xa4, 0xa3, 0x86, 0x7e, 0x03, 0xf7, 0x6f, 0xbe, 0x11, 0xdf, 0x7c, - 0xd3, 0x28, 0xa9, 0xef, 0x44, 0x28, 0x0f, 0xf5, 0xea, 0xdd, 0xdb, 0x46, 0x94, 0x78, 0xea, 0x6a, - 0xb2, 0xea, 0x7e, 0x64, 0x25, 0xb9, 0x23, 0x66, 0x75, 0x7c, 0xf0, 0x64, 0xfe, 0xaf, 0xec, 0x0b, - 0x36, 0x3c, 0x9f, 0xfc, 0x75, 0x15, 0x5a, 0xc5, 0xad, 0x6f, 0x55, 0xd6, 0x57, 0x54, 0xe9, 0x96, - 0xff, 0xe2, 0x7c, 0xd0, 0x19, 0x06, 0x5e, 0xff, 0xc4, 0xbf, 0xf3, 0x00, 0xf3, 0x4d, 0x37, 0xd4, - 0x7b, 0x16, 0xe5, 0x0f, 0x9b, 0x39, 0xa7, 0x73, 0x7a, 0xeb, 0xe6, 0x48, 0x2e, 0x12, 0xaf, 0x49, - 0x8a, 0x98, 0x60, 0x4d, 0x69, 0x17, 0x2b, 0x62, 0xbc, 0x9f, 0x94, 0x87, 0x4c, 0xcb, 0xdd, 0x59, - 0xdb, 0xb6, 0x75, 0x5a, 0x74, 0xb8, 0x76, 0x8c, 0x84, 0x93, 0xa5, 0x61, 0xb6, 0x33, 0x2d, 0xb5, - 0x05, 0xa6, 0x36, 0x97, 0x52, 0x28, 0x8b, 0xa0, 0x60, 0x42, 0x9b, 0xb7, 0x7b, 0x93, 0x54, 0x37, - 0x5a, 0xbc, 0xcc, 0x09, 0x59, 0x12, 0x37, 0x0a, 0xd5, 0xe2, 0x33, 0xfd, 0xa6, 0x46, 0xc3, 0xb6, - 0xd4, 0x41, 0x7c, 0xbd, 0x38, 0x2d, 0x1e, 0x44, 0xbb, 0xfa, 0xd5, 0x83, 0xd0, 0xb5, 0xf2, 0xd3, - 0xf3, 0x76, 0x03, 0x3e, 0xe8, 0xa1, 0x9b, 0xd0, 0x56, 0x62, 0xbb, 0x01, 0x1d, 0x75, 0xd5, 0xf5, - 0x3a, 0x8a, 0xb7, 0x9a, 0xa8, 0x30, 0x5b, 0x42, 0x91, 0x39, 0x52, 0x13, 0x0a, 0xca, 0x74, 0xbd, - 0xd2, 0x98, 0x76, 0x13, 0xa5, 0x5b, 0xd4, 0xaa, 0xf6, 0x21, 0xd5, 0xc1, 0x58, 0xa5, 0x9e, 0x1e, - 0x5d, 0xe4, 0x57, 0xfb, 0x00, 0x4f, 0x5a, 0xb2, 0x3f, 0xfd, 0xbb, 0x3e, 0x6a, 0xeb, 0x57, 0xfe, - 0x5e, 0x0a, 0x2d, 0xc3, 0x1e, 0x5d, 0xb9, 0x55, 0x3e, 0x99, 0xdb, 0x97, 0x5f, 0x41, 0x9f, 0xea, - 0x51, 0xdb, 0x1a, 0xe6, 0x4e, 0xf5, 0x2f, 0x8b, 0x4f, 0xf5, 0xab, 0xe7, 0x8f, 0x72, 0xb4, 0xea, - 0x8b, 0xd1, 0x93, 0x18, 0x36, 0x54, 0xb0, 0x5f, 0xee, 0x7e, 0x37, 0x7e, 0x01, 0xe2, 0x31, 0x12, - 0xeb, 0x67, 0x09, 0x24, 0x08, 0xf1, 0x38, 0xc6, 0xad, 0x55, 0x6d, 0xfe, 0x05, 0x9c, 0x5f, 0xd1, - 0xbe, 0xd2, 0x96, 0xa3, 0x3d, 0x2a, 0x5f, 0xd9, 0x37, 0x95, 0x4b, 0x3c, 0x6c, 0x4b, 0xe2, 0x65, - 0xb6, 0xb7, 0xb8, 0xd0, 0x62, 0xfc, 0x22, 0xce, 0x69, 0x67, 0x70, 0xa1, 0xa2, 0xd3, 0x49, 0xce, - 0xc8, 0x85, 0x27, 0x39, 0x07, 0xa6, 0x4c, 0xb4, 0x23, 0x09, 0xb7, 0x13, 0xde, 0xeb, 0xfc, 0xf6, - 0xe4, 0x40, 0x93, 0x53, 0xb5, 0x2e, 0x1c, 0xe4, 0xf4, 0xc5, 0xb9, 0xfa, 0xa2, 0xaf, 0xf9, 0x7d, - 0x5f, 0xf5, 0x35, 0x60, 0x99, 0xdd, 0x1c, 0x60, 0xf9, 0xec, 0xbb, 0x9f, 0xde, 0xa8, 0xc5, 0x1f, - 0xfa, 0xae, 0x56, 0x2c, 0x9e, 0x99, 0xc6, 0x59, 0xdf, 0x98, 0x5d, 0x18, 0xbb, 0xe6, 0x07, 0x86, - 0xd2, 0x59, 0xaa, 0x5f, 0x93, 0x52, 0x2b, 0x1e, 0xc6, 0xec, 0xe8, 0x41, 0x93, 0x67, 0xaa, 0xe5, - 0xb3, 0xfe, 0xb4, 0x09, 0x47, 0x7a, 0xd0, 0x67, 0xe7, 0x65, 0xfd, 0xe1, 0xe7, 0x92, 0x32, 0xee, - 0xa8, 0x0c, 0x45, 0x10, 0x2e, 0xfa, 0x59, 0x87, 0xa6, 0x63, 0x7d, 0xf4, 0x8f, 0x5d, 0x1d, 0xa2, - 0xaf, 0xff, 0x6b, 0x12, 0x50, 0x5f, 0xfb, 0x02, 0x31, 0xaa, 0x72, 0x7a, 0xd8, 0x75, 0xdf, 0x35, - 0xa4, 0x72, 0xd3, 0x9c, 0xe8, 0x1f, 0x1f, 0xb1, 0xe9, 0xc3, 0x9f, 0x7d, 0x2f, 0x56, 0x89, 0xc8, - 0x8c, 0x6b, 0x11, 0xaf, 0x8d, 0x97, 0xd7, 0xd9, 0xed, 0x12, 0xb1, 0x8f, 0xbe, 0x72, 0x7e, 0x2f, - 0xc7, 0x9e, 0x80, 0xff, 0xdc, 0xb2, 0xcd, 0x37, 0x89, 0x45, 0xad, 0xb0, 0x7c, 0xa9, 0x49, 0x1f, - 0xf3, 0x0a, 0xf9, 0x5b, 0x3f, 0xfc, 0xa3, 0x6b, 0xf4, 0x3f, 0x1c, 0xfa, 0x1f, 0xb9, 0x8d, 0x92, - 0xce, 0x88, 0x68, 0x00, 0x00 -}; \ No newline at end of file diff --git a/src/Apps.h b/src/Apps.h index a5287c45..961a9d13 100644 --- a/src/Apps.h +++ b/src/Apps.h @@ -16,7 +16,7 @@ #include #include #include - +#include "LookingEyes.h" Ticker downloader; tm timeInfo; @@ -585,6 +585,79 @@ void ShowCustomApp(String name, FastLED_NeoMatrix *matrix, MatrixDisplayUiState DisplayManager.getInstance().resetTextColor(); } +static unsigned long lastTime = 0; +void EyesApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, int16_t x, int16_t y, bool firstFrame, bool lastFrame, GifPlayer *gifPlayer) +{ + if (blinkCountdown < sizeof(blinkIndex) / sizeof(blinkIndex[0]) - 1) + { + matrix->drawRGBBitmap(6 + x, 0 + y, eye[blinkIndex[blinkCountdown]], 8, 8); + matrix->drawRGBBitmap(18 + x, 0 + y, eye[blinkIndex[blinkCountdown]], 8, 8); + } + else + { + matrix->drawRGBBitmap(6 + x, 0 + y, eye[0], 8, 8); + matrix->drawRGBBitmap(18 + x, 0 + y, eye[0], 8, 8); + } + + blinkCountdown--; + if (blinkCountdown == 0) + { + blinkCountdown = random(20, 250); + } + + if (gazeCountdown <= gazeFrames) + { + gazeCountdown--; + matrix->fillRect(newX - (dX * gazeCountdown / gazeFrames) + 6 + x, newY - (dY * gazeCountdown / gazeFrames) + y, 2, 2, 0); + matrix->fillRect(newX - (dX * gazeCountdown / gazeFrames) + 18 + x, newY - (dY * gazeCountdown / gazeFrames) + y, 2, 2, 0); + if (gazeCountdown == 0) + { + eyeX = newX; + eyeY = newY; + do + { + switch (PET_MOOD) + { + case 0: + newX = random(0, 6); + newY = random(0, 6); + dX = newX - 4; + dY = newY - 4; + break; + case 1: + newX = random(0, 7); + newY = random(0, 7); + dX = newX - 3; + dY = newY - 3; + break; + case 2: + newX = random(1, 7); + newY = random(1, 4); + dX = newX - 3; + dY = newY - 3; + break; + case 3: + newX = random(0, 7); + newY = random(3, 7); + dX = newX - 3; + dY = newY - 3; + break; + } + } while (((dX * dX + dY * dY) <= 3)); + dX = newX - eyeX; + dY = newY - eyeY; + gazeFrames = random(5, 9); + gazeCountdown = random(gazeFrames, 60); + } + } + else + { + gazeCountdown--; + matrix->fillRect(eyeX + 6 + x, eyeY + y, 2, 2, 0); + matrix->fillRect(eyeX + 18 + x, eyeY + y, 2, 2, 0); + } +} + void NotifyApp(FastLED_NeoMatrix *matrix, MatrixDisplayUiState *state, GifPlayer *gifPlayer) { // Check if notification flag is set diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 72a9e8eb..04c4deb3 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -332,7 +332,7 @@ bool parseFragmentsText(const String &jsonText, std::vector &colors, s void DisplayManager_::parseCustomPage(const String &name, const char *json) { - if (strcmp(json, "") == 0) + if ((strcmp(json, "") == 0) || (strcmp(json, "{}") == 0)) { removeCustomAppFromApps(name, true); return; @@ -369,7 +369,7 @@ void DisplayManager_::parseCustomPage(const String &name, const char *json) void DisplayManager_::generateCustomPage(const String &name, const char *json) { - DynamicJsonDocument doc(2048); + DynamicJsonDocument doc(4096); DeserializationError error = deserializeJson(doc, json); if (error) { @@ -590,7 +590,7 @@ void DisplayManager_::generateCustomPage(const String &name, const char *json) void DisplayManager_::generateNotification(const char *json) { - StaticJsonDocument<2048> doc; + StaticJsonDocument<4096> doc; deserializeJson(doc, json); notify.progress = doc.containsKey("progress") ? doc["progress"].as() : -1; @@ -814,6 +814,8 @@ void DisplayManager_::loadNativeApps() updateApp("bat", BatApp, SHOW_BAT, 4); #endif + updateApp("eyes", EyesApp, SHOW_EYES, 5); + ui->setApps(Apps); setAutoTransition(true); } @@ -836,9 +838,10 @@ void DisplayManager_::setup() } gif.setMatrix(matrix); ui->setAppAnimation(SLIDE_DOWN); + + ui->setTargetFPS(MATRIX_FPS); ui->setTimePerApp(TIME_PER_APP); ui->setTimePerTransition(TIME_PER_TRANSITION); - ui->setTargetFPS(MATRIX_FPS); ui->setOverlays(overlays, 4); setAutoTransition(AUTO_TRANSITION); ui->init(); @@ -909,6 +912,7 @@ void DisplayManager_::tick() } else if (MOODLIGHT_MODE) { + // handled by the moodlight function } else { @@ -928,15 +932,18 @@ void DisplayManager_::tick() } } - uint16_t ArtnetStatus = artnet.read(); - if (ArtnetStatus > 0) - { - lastArtnetStatusTime = millis(); - ARTNET_MODE = true; - } - else if (millis() - lastArtnetStatusTime > 1000) + if (!AP_MODE) { - ARTNET_MODE = false; + uint16_t ArtnetStatus = artnet.read(); + if (ArtnetStatus > 0) + { + lastArtnetStatusTime = millis(); + ARTNET_MODE = true; + } + else if (millis() - lastArtnetStatusTime > 1000) + { + ARTNET_MODE = false; + } } } @@ -981,7 +988,7 @@ void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t *d } } -void DisplayManager_::startE131() +void DisplayManager_::startArtnet() { artnet.begin(); artnet.setArtDmxCallback(onDmxFrame); @@ -1185,6 +1192,10 @@ std::pair getNativeAppByName(const String &appName) { return std::make_pair("time", TimeApp); } + if (appName == "eyes") + { + return std::make_pair("eyes", EyesApp); + } else if (appName == "date") { return std::make_pair("date", DateApp); @@ -1277,6 +1288,8 @@ void DisplayManager_::updateAppVector(const char *json) // Set the updated apps vector in the UI and save settings ui->setApps(Apps); saveSettings(); + sendAppLoop(); + setAutoTransition(AUTO_TRANSITION); } String DisplayManager_::getStats() @@ -1308,7 +1321,7 @@ String DisplayManager_::getStats() return serializeJson(doc, jsonString), jsonString; } -void DisplayManager_::setAppTime(uint16_t duration) +void DisplayManager_::setAppTime(long duration) { ui->setTimePerApp(duration); } @@ -1488,22 +1501,22 @@ void DisplayManager_::indicatorParser(uint8_t indicator, const char *json) { if (indicator == 1) { - ui->setIndicator1Blink(doc["blink"].as()); + ui->setIndicator1Blink(doc["blink"].as()); } else { - ui->setIndicator2Blink(doc["blink"].as()); + ui->setIndicator2Blink(doc["blink"].as()); } } else { if (indicator == 1) { - ui->setIndicator1Blink(false); + ui->setIndicator1Blink(0); } else { - ui->setIndicator2Blink(false); + ui->setIndicator2Blink(0); } } MQTTManager.setIndicatorState(1, ui->indicator1State, ui->indicator1Color); @@ -1561,7 +1574,7 @@ void DisplayManager_::setNewSettings(const char *json) if (doc.containsKey("ATIME")) { - int atime = doc["ATIME"].as(); + long atime = doc["ATIME"].as(); TIME_PER_APP = atime * 1000; } else @@ -1749,7 +1762,7 @@ void DisplayManager_::reorderApps(const String &jsonString) void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset, String &drawInstructions) { - StaticJsonDocument<512> doc; + StaticJsonDocument<4096> doc; DeserializationError error = deserializeJson(doc, drawInstructions); if (error) @@ -1821,9 +1834,9 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset, } else if (command == "dfc") { - int x = params[0].as(); - int y = params[1].as(); - int r = params[2].as(); + double x = params[0].as(); + double y = params[1].as(); + double r = params[2].as(); auto color6 = params[3]; uint16_t color = getColorFromJsonVariant(color6, TEXTCOLOR_565); matrix->fillCircle(x + xOffset, y + yOffset, r, color); @@ -1839,6 +1852,30 @@ void DisplayManager_::processDrawInstructions(int16_t xOffset, int16_t yOffset, matrix->setTextColor(color); matrix->print(text); } + else if (command == "db") + { + int x = params[0].as(); + int y = params[1].as(); + int w = params[2].as(); + int h = params[3].as(); + + // Create an array to hold the color data + uint16_t bitmap[w * h]; + + // Assume that params[4] is a JsonArray + JsonArray colorArray = params[4].as(); + + // Load the color data into the array + int i = 0; + for (JsonVariant v : colorArray) + { + bitmap[i] = v.as(); + i++; + } + + // Draw the bitmap + matrix->drawRGBBitmap(x + xOffset, y + yOffset, bitmap, w, h); + } } } } diff --git a/src/DisplayManager.h b/src/DisplayManager.h index 7b1c27a9..5624901a 100644 --- a/src/DisplayManager.h +++ b/src/DisplayManager.h @@ -1,13 +1,11 @@ #ifndef DisplayManager_h #define DisplayManager_h - #include #include #include #include - class DisplayManager_ { private: @@ -66,7 +64,7 @@ class DisplayManager_ void drawLineChart(int16_t x, int16_t y, const int data[], byte dataSize, bool withIcon, uint16_t color); void updateAppVector(const char *json); void setMatrixLayout(int layout); - void setAppTime(uint16_t duration); + void setAppTime(long duration); String getAppsAsJson(); String getStats(); String getSettings(); @@ -85,7 +83,7 @@ class DisplayManager_ void processDrawInstructions(int16_t x, int16_t y, String &drawInstructions); String ledsAsJson(); String getAppsWithIcon(); - void startE131(); + void startArtnet(); void parseCustomPage(const String &name, const char *json); void moodlight(const char *json); }; diff --git a/src/Globals.cpp b/src/Globals.cpp index e91d23dd..fc3dbc86 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -150,6 +150,7 @@ void loadSettings() START_ON_MONDAY = Settings.getBool("SOM", true); IS_CELSIUS = Settings.getBool("CEL", true); SHOW_TIME = Settings.getBool("TIM", true); + SHOW_EYES = Settings.getBool("EYE", true); SHOW_DATE = Settings.getBool("DAT", true); SHOW_TEMP = Settings.getBool("TEMP", true); SHOW_HUM = Settings.getBool("HUM", true); @@ -194,6 +195,7 @@ void saveSettings() Settings.putBool("SOM", START_ON_MONDAY); Settings.putBool("CEL", IS_CELSIUS); Settings.putBool("TIM", SHOW_TIME); + Settings.putBool("EYE", SHOW_EYES); Settings.putBool("DAT", SHOW_DATE); Settings.putBool("TEMP", SHOW_TEMP); Settings.putBool("HUM", SHOW_HUM); @@ -214,7 +216,7 @@ IPAddress gateway; IPAddress subnet; IPAddress primaryDNS; IPAddress secondaryDNS; -const char *VERSION = "0.61"; +const char *VERSION = "0.62"; String MQTT_HOST = ""; uint16_t MQTT_PORT = 1883; @@ -224,6 +226,7 @@ String MQTT_PREFIX; bool IO_BROKER = false; bool NET_STATIC = false; bool SHOW_TIME = true; +bool SHOW_EYES = true; bool SHOW_DATE = true; bool SHOW_WEATHER = true; #ifdef ULANZI diff --git a/src/Globals.h b/src/Globals.h index 0aca7792..0f522d47 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -50,6 +50,7 @@ extern bool SHOW_TEMP; extern bool SHOW_HUM; extern bool SHOW_SECONDS; extern bool SHOW_WEEKDAY; +extern bool SHOW_EYES; extern String NET_IP; extern String NET_GW; extern String NET_SN; diff --git a/src/LookingEyes.h b/src/LookingEyes.h new file mode 100644 index 00000000..6f4b43d6 --- /dev/null +++ b/src/LookingEyes.h @@ -0,0 +1,21 @@ +int blinkIndex[] = {1, 2, 3, 4, 3, 2, 1}; + +int blinkCountdown = 60; +int gazeCountdown = 30; +int gazeFrames = 5; + +int eyeX = 9; +int eyeY = 3; +int newX = 9; +int newY = 3; +int dX = 6; +int dY = 0; +int PET_MOOD = 2; + +uint16_t eye[5][64] = { + {0, 0, 65535, 65535, 65535, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535, 65535, 65535, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535, 65535, 65535, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 0, 65535, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 0, 0, 0, 0, 0, 0, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; diff --git a/src/MQTTManager.cpp b/src/MQTTManager.cpp index 7abb0c77..acd4a4e9 100644 --- a/src/MQTTManager.cpp +++ b/src/MQTTManager.cpp @@ -68,7 +68,6 @@ void onSwitchCommand(bool state, HASwitch *sender) void onSelectCommand(int8_t index, HASelect *sender) { - sender->setState(index); // report the selected option back to the HA panel switch (index) { @@ -80,7 +79,6 @@ void onSelectCommand(int8_t index, HASelect *sender) AUTO_BRIGHTNESS = true; break; } - saveSettings(); } @@ -236,7 +234,7 @@ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length) delete[] payloadCopy; return; } - if (strTopic.equals(MQTT_PREFIX + "/moodlight")) + if (strTopic.equals(MQTT_PREFIX + "/moodlight")) { DisplayManager.moodlight(payloadCopy); delete[] payloadCopy; diff --git a/src/MatrixDisplayUi.cpp b/src/MatrixDisplayUi.cpp index bd1c756a..24931578 100644 --- a/src/MatrixDisplayUi.cpp +++ b/src/MatrixDisplayUi.cpp @@ -55,7 +55,7 @@ void MatrixDisplayUi::setTargetFPS(uint8_t fps) // Calculate new ticksPerApp float changeRatio = oldInterval / (float)this->updateInterval; - this->ticksPerApp *= changeRatio; + // this->ticksPerApp *= changeRatio; this->ticksPerTransition *= changeRatio; } @@ -81,7 +81,7 @@ void MatrixDisplayUi::setsetAutoTransitionBackwards() } void MatrixDisplayUi::setTimePerApp(long time) { - this->ticksPerApp = time / (long)updateInterval; + this->ticksPerApp = time / updateInterval; } void MatrixDisplayUi::setTimePerTransition(uint16_t time) { @@ -242,6 +242,7 @@ void MatrixDisplayUi::drawIndicators() matrix->drawPixel(30, 0, indicator1Color); matrix->drawPixel(31, 1, indicator1Color); } + if (indicator2State && !indicator2Blink) { matrix->drawPixel(31, 7, indicator2Color); @@ -249,14 +250,14 @@ void MatrixDisplayUi::drawIndicators() matrix->drawPixel(30, 7, indicator2Color); } - if (indicator1State && indicator1Blink && (millis() % 1000) < 500) + if (indicator1State && indicator1Blink && (millis() % (2 * indicator1Blink)) < indicator1Blink) { matrix->drawPixel(31, 0, indicator1Color); matrix->drawPixel(30, 0, indicator1Color); matrix->drawPixel(31, 1, indicator1Color); } - if (indicator2State && indicator2Blink && (millis() % 1000) < 500) + if (indicator2State && indicator2Blink && (millis() % (2 * indicator2Blink)) < indicator2Blink) { matrix->drawPixel(31, 7, indicator2Color); matrix->drawPixel(31, 6, indicator2Color); @@ -264,6 +265,7 @@ void MatrixDisplayUi::drawIndicators() } } + void MatrixDisplayUi::drawApp() { switch (this->state.appState) @@ -372,12 +374,12 @@ void MatrixDisplayUi::setIndicator2State(bool state) this->indicator2State = state; } -void MatrixDisplayUi::setIndicator1Blink(bool blink) +void MatrixDisplayUi::setIndicator1Blink(int blink) { this->indicator1Blink = blink; } -void MatrixDisplayUi::setIndicator2Blink(bool blink) +void MatrixDisplayUi::setIndicator2Blink(int blink) { this->indicator2Blink = blink; } diff --git a/src/MatrixDisplayUi.h b/src/MatrixDisplayUi.h index db60523b..c60db32c 100644 --- a/src/MatrixDisplayUi.h +++ b/src/MatrixDisplayUi.h @@ -28,13 +28,11 @@ #ifndef MatrixDisplayUi_h #define MatrixDisplayUi_h - #include #include "FastLED_NeoMatrix.h" #include "GifPlayer.h" #include "DisplayManager.h" - #ifndef DEBUG_MatrixDisplayUi #define DEBUG_MatrixDisplayUi(...) #endif @@ -56,7 +54,7 @@ struct MatrixDisplayUiState { u_int64_t lastUpdate = 0; - uint16_t ticksSinceLastStateSwitch = 0; + long ticksSinceLastStateSwitch = 0; AppState appState = FIXED; uint8_t currentApp = 0; @@ -82,7 +80,7 @@ class MatrixDisplayUi AnimationDirection appAnimationDirection = SLIDE_DOWN; int8_t lastTransitionDirection = 1; - long ticksPerApp = 151; // ~ 5000ms at 30 FPS + long ticksPerApp = 151; // ~ 5000ms at 30 FPS uint16_t ticksPerTransition = 15; // ~ 500ms at 30 FPS bool setAutoTransition = true; @@ -100,7 +98,7 @@ class MatrixDisplayUi MatrixDisplayUiState state; // Bookeeping for update - uint8_t updateInterval = 33; + long updateInterval = 33; void drawApp(); void drawOverlays(); @@ -154,8 +152,8 @@ class MatrixDisplayUi void setIndicator2Color(uint16_t color); void setIndicator2State(bool state); - void setIndicator1Blink(bool Blink); - void setIndicator2Blink(bool Blink); + void setIndicator1Blink(int Blink); + void setIndicator2Blink(int Blink); void drawIndicators(); // Customize indicator position and style @@ -203,7 +201,7 @@ class MatrixDisplayUi uint16_t indicator2Color = 31; bool indicator1State = false; bool indicator2State = false; - bool indicator1Blink = false; - bool indicator2Blink = false; + int indicator1Blink = 0; + int indicator2Blink = 0; }; #endif diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 535e0793..9dc21234 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -4,7 +4,7 @@ #include #include #include -//#include +// #include #include #include @@ -50,7 +50,7 @@ const char *menuItems[] PROGMEM = { "APPS", "SOUND", #ifndef ULANZI - "VOLUME" , + "VOLUME", #endif "UPDATE"}; @@ -88,19 +88,8 @@ const char *dateFormat[] PROGMEM = { int8_t dateFormatIndex; uint8_t dateFormatCount = 9; -const char *appsItems[][2] PROGMEM = { - {"13", "time"}, - {"1158", "date"}, - {"234", "temp"}, -#ifdef ULANZI - {"2075", "hum"}, - {"1486", "bat"}}; -#else - {"2075", "hum"}}; -#endif - int8_t appsIndex; -uint8_t appsCount = 5; +uint8_t appsCount = 6; MenuState currentState = MainMenu; @@ -200,6 +189,9 @@ String MenuManager_::menutext() case 4: DisplayManager.drawBMP(0, 0, icon_1486, 8, 8); return SHOW_BAT ? "ON" : "OFF"; + case 5: + DisplayManager.drawBMP(0, 0, eyes, 8, 8); + return SHOW_EYES ? "ON" : "OFF"; #endif default: break; @@ -339,7 +331,7 @@ void MenuManager_::leftButton() VOLUME_PERCENT = 100; else VOLUME_PERCENT--; -#endif +#endif default: break; } @@ -397,7 +389,7 @@ void MenuManager_::selectButton() #ifndef ULANZI currentState = VolumeMenu; break; -#endif +#endif case 13: if (UpdateManager.checkUpdate(true)) { @@ -436,6 +428,9 @@ void MenuManager_::selectButton() SHOW_BAT = !SHOW_BAT; break; #endif + case 5: + SHOW_EYES = !SHOW_EYES; + break; default: break; } @@ -492,7 +487,7 @@ void MenuManager_::selectButtonLong() saveSettings(); break; #ifndef ULANZI - case VolumeMenu: + case VolumeMenu: VOLUME = map(VOLUME_PERCENT, 0, 100, 0, 30); PeripheryManager.setVolume(VOLUME); saveSettings(); diff --git a/src/PeripheryManager.cpp b/src/PeripheryManager.cpp index 7b38fb9b..ba3651ea 100644 --- a/src/PeripheryManager.cpp +++ b/src/PeripheryManager.cpp @@ -327,7 +327,7 @@ void PeripheryManager_::tick() previousMillis_BatTempHum = currentMillis_BatTempHum; #ifdef ULANZI uint16_t ADCVALUE = analogRead(BATTERY_PIN); - BATTERY_PERCENT = min((int)map(ADCVALUE, 475, 665, 0, 100), 100); + BATTERY_PERCENT = max(min((int)map(ADCVALUE, 475, 665, 0, 100), 100), 0); BATTERY_RAW = ADCVALUE; #endif if (SENSOR_READING) diff --git a/src/icons.h b/src/icons.h index cf263471..87c1890b 100644 --- a/src/icons.h +++ b/src/icons.h @@ -23,5 +23,6 @@ const uint16_t icon_234[] = {0, 65535, 65535, 65535, 0, 0, 0, 0, 0, 65535, 0, 65 const uint16_t icon_2075[] = {0, 0, 61279, 0, 0, 0, 0, 0, 0, 65535, 59199, 50751, 0, 0, 0, 0, 65535, 61279, 59199, 50751, 44383, 0, 0, 0, 61279, 59199, 59199, 44383, 44383, 0, 0, 0, 61279, 50751, 50751, 44383, 31737, 0, 0, 0, 0, 44383, 44383, 31737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const uint16_t icon_1486[] = {0, 0, 2016, 2016, 2016, 0, 0, 0, 0, 2016, 2016, 2914, 2016, 2016, 0, 0, 0, 2016, 2914, 2914, 2914, 2016, 0, 0, 0, 2016, 2914, 2914, 2914, 2016, 0, 0, 0, 2016, 2914, 2914, 2914, 2016, 0, 0, 0, 2016, 2914, 2914, 2914, 2016, 0, 0, 0, 2016, 2914, 2914, 2914, 2016, 0, 0, 0, 2016, 2016, 2016, 2016, 2016, 0, 0}; +const uint16_t eyes[] = {0, 0, 65535, 65535, 65535, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 0, 0}; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 49e8a7d2..922eb396 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,13 +70,13 @@ void setup() delay(500); xTaskCreatePinnedToCore(BootAnimation, "Task", 10000, NULL, 1, &taskHandle, 0); ServerManager.setup(); - //PeripheryManager.playBootSound(); + // PeripheryManager.playBootSound(); if (ServerManager.isConnected) { MQTTManager.setup(); DisplayManager.loadNativeApps(); UpdateManager.setup(); - DisplayManager.startE131(); + DisplayManager.startArtnet(); StopTask = true; float x = 4; while (x >= -85)