2020-09-28 08:44:14 +00:00
|
|
|
#include "ESPUI.h"
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#include <functional>
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#include <ESPAsyncWebServer.h>
|
2017-11-28 12:48:58 +00:00
|
|
|
|
2018-05-27 09:47:53 +00:00
|
|
|
#include "dataControlsJS.h"
|
2019-04-15 11:49:15 +00:00
|
|
|
#include "dataGraphJS.h"
|
2020-09-28 08:40:31 +00:00
|
|
|
#include "dataIndexHTML.h"
|
|
|
|
#include "dataNormalizeCSS.h"
|
2018-05-27 09:47:53 +00:00
|
|
|
#include "dataSliderJS.h"
|
2020-09-28 08:40:31 +00:00
|
|
|
#include "dataStyleCSS.h"
|
2019-03-03 21:21:21 +00:00
|
|
|
#include "dataTabbedcontentJS.h"
|
2018-05-27 09:47:53 +00:00
|
|
|
#include "dataZeptoJS.h"
|
2017-11-28 12:48:58 +00:00
|
|
|
|
2020-10-02 17:08:45 +00:00
|
|
|
uint16_t Control::idCounter = 1;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
// ################# LITTLEFS functions
|
2018-01-14 11:22:26 +00:00
|
|
|
#if defined(ESP32)
|
2020-09-28 08:40:31 +00:00
|
|
|
void listDir(const char* dirname, uint8_t levels)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
2020-06-23 18:34:05 +00:00
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
2020-10-18 09:06:38 +00:00
|
|
|
Serial.printf_P(PSTR("Listing directory: %s\n"), dirname);
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
#endif
|
2018-01-08 11:26:32 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
File root = LITTLEFS.open(dirname);
|
2020-10-18 09:06:38 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
File root = LittleFS.open(dirname);
|
2020-10-18 09:06:38 +00:00
|
|
|
#endif
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!root)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Failed to open directory"));
|
|
|
|
}
|
|
|
|
#endif
|
2018-01-14 11:22:26 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-01-08 11:26:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!root.isDirectory())
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Not a directory"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
2020-06-23 18:34:05 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
|
|
|
|
File file = root.openNextFile();
|
|
|
|
|
|
|
|
while (file)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (file.isDirectory())
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F(" DIR : "));
|
|
|
|
Serial.println(file.name());
|
|
|
|
}
|
|
|
|
#endif
|
2018-01-14 11:22:26 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (levels)
|
|
|
|
{
|
|
|
|
listDir(file.name(), levels - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F(" FILE: "));
|
|
|
|
Serial.print(file.name());
|
|
|
|
Serial.print(F(" SIZE: "));
|
|
|
|
Serial.println(file.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
file = root.openNextFile();
|
|
|
|
}
|
2018-01-08 11:26:32 +00:00
|
|
|
}
|
2018-01-14 11:22:26 +00:00
|
|
|
#else
|
2018-01-08 11:26:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void listDir(const char* dirname, uint8_t levels)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
// ignoring levels for esp8266
|
|
|
|
Serial.printf_P(PSTR("Listing directory: %s\n"), dirname);
|
|
|
|
|
|
|
|
String str = "";
|
|
|
|
Dir dir = LittleFS.openDir("/");
|
|
|
|
|
|
|
|
while (dir.next())
|
|
|
|
{
|
|
|
|
Serial.print(F(" FILE: "));
|
|
|
|
Serial.print(dir.fileName());
|
|
|
|
Serial.print(F(" SIZE: "));
|
|
|
|
Serial.println(dir.fileSize());
|
|
|
|
}
|
2018-01-14 11:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
void ESPUIClass::list()
|
|
|
|
{
|
2020-09-27 11:20:14 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
if (!LITTLEFS.begin())
|
2021-10-29 17:20:20 +00:00
|
|
|
{
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(F("LITTLEFS Mount Failed"));
|
2021-10-29 17:20:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (!LittleFS.begin())
|
|
|
|
{
|
|
|
|
Serial.println(F("LittleFS Mount Failed"));
|
|
|
|
return;
|
|
|
|
}
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
listDir("/", 1);
|
2018-01-14 11:22:26 +00:00
|
|
|
#if defined(ESP32)
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(LITTLEFS.totalBytes());
|
|
|
|
Serial.println(LITTLEFS.usedBytes());
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
#else
|
|
|
|
FSInfo fs_info;
|
2020-09-28 08:40:31 +00:00
|
|
|
LittleFS.info(fs_info);
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
Serial.println(fs_info.totalBytes);
|
|
|
|
Serial.println(fs_info.usedBytes);
|
2018-01-14 11:22:26 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void deleteFile(const char* path)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2021-10-29 17:20:20 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
bool exists = LITTLEFS.exists(path);
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
bool exists = LittleFS.exists(path);
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
if (!exists)
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.printf_P(PSTR("File: %s does not exist, not deleting\n"), path);
|
|
|
|
}
|
|
|
|
#endif
|
2017-11-28 12:48:58 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-11-29 10:32:07 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.printf_P(PSTR("Deleting file: %s\n"), path);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-09-27 11:20:14 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
bool didRemove = LITTLEFS.remove(path);
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
bool didRemove = LittleFS.remove(path);
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2021-10-29 17:20:20 +00:00
|
|
|
if (didRemove)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("File deleted"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Delete failed"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2017-11-28 12:48:58 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void writeFile(const char* path, const char* data)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-10-18 09:06:38 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.printf_P(PSTR("Writing file: %s\n"), path);
|
|
|
|
}
|
|
|
|
#endif
|
2020-09-27 11:20:14 +00:00
|
|
|
|
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
File file = LITTLEFS.open(path, FILE_WRITE);
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
File file = LittleFS.open(path, FILE_WRITE);
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
if (!file)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Failed to open file for writing"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2018-11-26 17:25:10 +00:00
|
|
|
#if defined(ESP32)
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (file.print(data))
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("File written"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
else
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Write failed"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
|
|
|
|
2018-11-26 17:25:10 +00:00
|
|
|
#else
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (file.print(FPSTR(data)))
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("File written"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
else
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Write failed"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
|
|
|
|
2018-11-26 17:25:10 +00:00
|
|
|
#endif
|
2020-09-28 08:40:31 +00:00
|
|
|
file.close();
|
2017-11-29 13:36:19 +00:00
|
|
|
}
|
2017-11-28 12:48:58 +00:00
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
// end LITTLEFS functions
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
void ESPUIClass::prepareFileSystem()
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
// this function should only be used once
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("About to prepare filesystem..."));
|
|
|
|
}
|
|
|
|
#endif
|
2017-12-25 15:39:54 +00:00
|
|
|
|
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
LITTLEFS.format();
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
if (!LITTLEFS.begin(true))
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(F("LITTLEFS Mount Failed"));
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
listDir("/", 1);
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(F("LITTLEFS Mount ESP32 Done"));
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2017-12-25 15:39:54 +00:00
|
|
|
#else
|
2020-09-28 08:40:31 +00:00
|
|
|
LittleFS.format();
|
|
|
|
LittleFS.begin();
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(F("LITTLEFS Mount ESP8266 Done"));
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2017-12-25 15:39:54 +00:00
|
|
|
#endif
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
deleteFile("/index.htm");
|
2018-01-08 11:26:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
deleteFile("/css/style.css");
|
|
|
|
deleteFile("/css/normalize.css");
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
deleteFile("/js/zepto.min.js");
|
|
|
|
deleteFile("/js/controls.js");
|
|
|
|
deleteFile("/js/slider.js");
|
|
|
|
deleteFile("/js/graph.js");
|
|
|
|
deleteFile("/js/tabbedcontent.js");
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Cleanup done"));
|
|
|
|
}
|
|
|
|
#endif
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// Now write
|
|
|
|
writeFile("/index.htm", HTML_INDEX);
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
writeFile("/css/style.css", CSS_STYLE);
|
|
|
|
writeFile("/css/normalize.css", CSS_NORMALIZE);
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
writeFile("/js/zepto.min.js", JS_ZEPTO);
|
|
|
|
writeFile("/js/controls.js", JS_CONTROLS);
|
|
|
|
writeFile("/js/slider.js", JS_SLIDER);
|
|
|
|
writeFile("/js/graph.js", JS_GRAPH);
|
2019-04-15 11:49:15 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
writeFile("/js/tabbedcontent.js", JS_TABBEDCONTENT);
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Done Initializing filesystem :-)"));
|
|
|
|
}
|
|
|
|
#endif
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2018-01-14 11:22:26 +00:00
|
|
|
#if defined(ESP32)
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
listDir("/", 1);
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2018-01-14 11:22:26 +00:00
|
|
|
#endif
|
2018-01-08 11:26:32 +00:00
|
|
|
|
2020-09-24 19:56:32 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
LITTLEFS.end();
|
2020-09-24 19:56:32 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
LittleFS.end();
|
2020-09-24 19:56:32 +00:00
|
|
|
#endif
|
2017-11-28 12:48:58 +00:00
|
|
|
}
|
|
|
|
|
2017-10-16 13:00:53 +00:00
|
|
|
// Handle Websockets Communication
|
2020-09-28 08:40:31 +00:00
|
|
|
void onWsEvent(
|
|
|
|
AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
switch (type)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2021-10-29 17:20:20 +00:00
|
|
|
case WS_EVT_DISCONNECT: {
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("Disconnected!\n"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
case WS_EVT_PONG: {
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("Received PONG!\n"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
case WS_EVT_ERROR: {
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("WebSocket Error!\n"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-05-13 17:44:56 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
case WS_EVT_CONNECT: {
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("Connected: "));
|
|
|
|
Serial.println(client->id());
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
ESPUI.jsonDom(0, client);
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("JSON Data Sent to Client!"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-24 17:10:21 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
break;
|
2019-03-08 21:22:01 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
case WS_EVT_DATA: {
|
2020-09-28 08:40:31 +00:00
|
|
|
String msg = "";
|
|
|
|
msg.reserve(len + 1);
|
2018-05-13 17:44:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
msg += (char)data[i];
|
|
|
|
}
|
2019-03-04 19:49:18 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
if (msg.startsWith(F("uiok:")))
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
int idx = msg.substring(msg.indexOf(':') + 1).toInt();
|
2022-01-20 20:43:04 +00:00
|
|
|
ESPUI.jsonDom(idx, client);
|
2022-01-12 20:12:20 +00:00
|
|
|
} else
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
uint16_t id = msg.substring(msg.lastIndexOf(':') + 1).toInt();
|
|
|
|
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
Serial.print(F("WS rec: "));
|
|
|
|
Serial.println(msg);
|
|
|
|
Serial.print(F("WS recognised ID: "));
|
2020-09-28 08:40:31 +00:00
|
|
|
Serial.println(id);
|
|
|
|
}
|
2022-01-12 20:12:20 +00:00
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
Control* c = ESPUI.getControl(id);
|
2019-03-04 19:49:18 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
if (c == nullptr)
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("No control found for ID "));
|
|
|
|
Serial.println(id);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
2019-03-24 17:10:21 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
if (c->callback == nullptr)
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.print(F("No callback found for ID "));
|
|
|
|
Serial.println(id);
|
|
|
|
}
|
|
|
|
#endif
|
2018-11-26 17:25:10 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.startsWith(F("bdown:")))
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
c->callback(c, B_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("bup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, B_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pfdown:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_FOR_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pfup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_FOR_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pldown:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_LEFT_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("plup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_LEFT_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("prdown:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_RIGHT_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("prup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_RIGHT_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pbdown:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_BACK_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pbup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_BACK_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pcdown:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_CENTER_DOWN);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("pcup:")))
|
|
|
|
{
|
|
|
|
c->callback(c, P_CENTER_UP);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("sactive:")))
|
|
|
|
{
|
|
|
|
c->value = "1";
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, S_ACTIVE);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("sinactive:")))
|
|
|
|
{
|
|
|
|
c->value = "0";
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, S_INACTIVE);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("slvalue:")))
|
|
|
|
{
|
|
|
|
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, SL_VALUE);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("nvalue:")))
|
|
|
|
{
|
|
|
|
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, N_VALUE);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("tvalue:")))
|
|
|
|
{
|
|
|
|
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, T_VALUE);
|
|
|
|
}
|
|
|
|
else if (msg.startsWith("tabvalue:"))
|
|
|
|
{
|
|
|
|
c->callback(c, client->id());
|
|
|
|
}
|
|
|
|
else if (msg.startsWith(F("svalue:")))
|
|
|
|
{
|
|
|
|
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
|
|
|
|
ESPUI.updateControl(c, client->id());
|
|
|
|
c->callback(c, S_VALUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Malformated message from the websocket"));
|
|
|
|
}
|
|
|
|
#endif
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-24 17:10:21 +00:00
|
|
|
break;
|
2020-09-28 08:40:31 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
2017-10-16 22:10:48 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color,
|
|
|
|
uint16_t parentControl, void (*callback)(Control*, int))
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2021-10-29 17:47:46 +00:00
|
|
|
Control* control = new Control(type, label, callback, value, color, true, parentControl);
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (this->controls == nullptr)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
this->controls = control;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Control* iterator = this->controls;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
while (iterator->next != nullptr)
|
|
|
|
{
|
|
|
|
iterator = iterator->next;
|
|
|
|
}
|
2018-05-13 18:19:29 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
iterator->next = control;
|
|
|
|
}
|
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
this->controlCount++;
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return control->id;
|
2018-05-13 18:19:29 +00:00
|
|
|
}
|
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
bool ESPUIClass::removeControl(uint16_t id, bool force_reload_ui)
|
2020-06-15 09:06:34 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (nullptr == this->controls)
|
|
|
|
return false;
|
2020-06-15 09:06:34 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* it = this->controls;
|
2020-06-23 18:34:05 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (id == it->id)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
this->controls = it->next;
|
|
|
|
delete it;
|
2022-01-12 20:12:20 +00:00
|
|
|
this->controlCount--;
|
2020-09-28 08:40:31 +00:00
|
|
|
if (force_reload_ui)
|
|
|
|
{
|
|
|
|
jsonReload();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
jsonDom(0);
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
return true;
|
2020-06-15 09:06:34 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
|
|
|
|
Control* it_next = it->next;
|
|
|
|
while (nullptr != it_next && id != it_next->id)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
it = it_next;
|
|
|
|
it_next = it_next->next;
|
2020-06-23 18:34:05 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
|
|
|
|
if (nullptr != it_next)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
it->next = it_next->next;
|
|
|
|
delete it_next;
|
2022-01-12 20:12:20 +00:00
|
|
|
this->controlCount--;
|
2020-09-28 08:40:31 +00:00
|
|
|
if (force_reload_ui)
|
|
|
|
{
|
|
|
|
jsonReload();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
jsonDom(0); // resends to all
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
|
|
|
return true;
|
2020-06-23 18:34:05 +00:00
|
|
|
}
|
2020-06-15 09:06:34 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return false;
|
2020-06-15 09:06:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::label(const char* label, ControlColor color, const String& value)
|
|
|
|
{
|
|
|
|
return addControl(ControlType::Label, label, value, color);
|
|
|
|
}
|
2017-11-28 12:48:58 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::graph(const char* label, ControlColor color)
|
|
|
|
{
|
|
|
|
return addControl(ControlType::Graph, label, "", color);
|
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::slider(
|
|
|
|
const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min, int max)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t sliderId = addControl(ControlType::Slider, label, String(value), color, Control::noParent, callback);
|
|
|
|
addControl(ControlType::Min, label, String(min), ControlColor::None, sliderId);
|
|
|
|
addControl(ControlType::Max, label, String(max), ControlColor::None, sliderId);
|
2019-03-24 18:18:53 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return sliderId;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2017-11-13 16:22:02 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::button(const char* label, void (*callback)(Control*, int), ControlColor color, const String& value)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::Button, label, value, color, Control::noParent, callback);
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2017-11-13 16:22:02 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::switcher(const char* label, void (*callback)(Control*, int), ControlColor color, bool startState)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::Switcher, label, startState ? "1" : "0", color, Control::noParent, callback);
|
2017-10-16 13:00:53 +00:00
|
|
|
}
|
2017-10-19 11:46:47 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::pad(const char* label, void (*callback)(Control*, int), ControlColor color)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::Pad, label, "", color, Control::noParent, callback);
|
2019-03-24 18:18:53 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::padWithCenter(const char* label, void (*callback)(Control*, int), ControlColor color)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::PadWithCenter, label, "", color, Control::noParent, callback);
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::number(
|
|
|
|
const char* label, void (*callback)(Control*, int), ControlColor color, int number, int min, int max)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t numberId = addControl(ControlType::Number, label, String(number), color, Control::noParent, callback);
|
|
|
|
addControl(ControlType::Min, label, String(min), ControlColor::None, numberId);
|
|
|
|
addControl(ControlType::Max, label, String(max), ControlColor::None, numberId);
|
|
|
|
return numberId;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::gauge(const char* label, ControlColor color, int number, int min, int max)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t numberId = addControl(ControlType::Gauge, label, String(number), color, Control::noParent);
|
|
|
|
addControl(ControlType::Min, label, String(min), ControlColor::None, numberId);
|
|
|
|
addControl(ControlType::Max, label, String(max), ControlColor::None, numberId);
|
|
|
|
return numberId;
|
2019-03-26 15:22:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 20:58:22 +00:00
|
|
|
uint16_t ESPUIClass::separator(const char* label) {
|
|
|
|
return addControl(ControlType::Separator, label, "", ControlColor::Alizarin, Control::noParent, nullptr);
|
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::accelerometer(const char* label, void (*callback)(Control*, int), ControlColor color)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::Accel, label, "", color, Control::noParent, callback);
|
2019-03-26 15:22:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
uint16_t ESPUIClass::text(const char* label, void (*callback)(Control*, int), ControlColor color, const String& value)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return addControl(ControlType::Text, label, value, color, Control::noParent, callback);
|
2017-10-19 11:46:47 +00:00
|
|
|
}
|
2017-05-18 22:05:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* ESPUIClass::getControl(uint16_t id)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* control = this->controls;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
while (control != nullptr)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (control->id == id)
|
|
|
|
{
|
|
|
|
return control;
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
control = control->next;
|
|
|
|
}
|
2018-05-13 18:19:29 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
return nullptr;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateControl(Control* control, int clientId)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!control)
|
2020-08-26 20:00:20 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return;
|
2020-08-26 20:00:20 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
|
2022-01-13 21:29:22 +00:00
|
|
|
if (this->ws == nullptr)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
String json;
|
|
|
|
DynamicJsonDocument document(jsonUpdateDocumentSize);
|
|
|
|
JsonObject root = document.to<JsonObject>();
|
|
|
|
|
|
|
|
root["type"] = (int)control->type + ControlType::UpdateOffset;
|
|
|
|
root["value"] = control->value;
|
|
|
|
root["id"] = control->id;
|
2021-10-29 17:47:46 +00:00
|
|
|
root["visible"] = control->visible;
|
2020-09-28 08:40:31 +00:00
|
|
|
root["color"] = (int)control->color;
|
2022-01-02 21:56:32 +00:00
|
|
|
if (control->panelStyle != 0)
|
|
|
|
root["panelStyle"] = control->panelStyle;
|
|
|
|
if (control->elementStyle != 0)
|
|
|
|
root["elementStyle"] = control->elementStyle;
|
2020-09-28 08:40:31 +00:00
|
|
|
serializeJson(document, json);
|
|
|
|
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
Serial.println(json);
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (clientId < 0)
|
|
|
|
{
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
|
|
|
{
|
|
|
|
Serial.println(F("TextAll"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
this->ws->textAll(json);
|
|
|
|
return;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
// This is a hacky workaround because ESPAsyncWebServer does not have a
|
|
|
|
// function like this and it's clients array is private
|
|
|
|
int tryId = 0;
|
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
for (size_t count = 0; count < this->ws->count();)
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
|
|
|
if (this->ws->hasClient(tryId))
|
|
|
|
{
|
|
|
|
if (clientId != tryId)
|
|
|
|
{
|
|
|
|
this->ws->client(tryId)->text(json);
|
|
|
|
}
|
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
2019-03-24 14:44:27 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
tryId++;
|
|
|
|
}
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
2019-03-08 21:22:01 +00:00
|
|
|
|
2022-01-02 21:56:32 +00:00
|
|
|
void ESPUIClass::setPanelStyle(uint16_t id, String style, int clientId)
|
|
|
|
{
|
|
|
|
Control* control = getControl(id);
|
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control->panelStyle = style;
|
|
|
|
updateControl(control, clientId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ESPUIClass::setElementStyle(uint16_t id, String style, int clientId)
|
|
|
|
{
|
|
|
|
Control* control = getControl(id);
|
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control->elementStyle = style;
|
|
|
|
updateControl(control, clientId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-08 21:25:10 +00:00
|
|
|
void ESPUIClass::setPanelWide(uint16_t id, bool wide) {
|
|
|
|
Control* control = getControl(id);
|
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control->wide = wide;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
void ESPUIClass::updateControl(uint16_t id, int clientId)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* control = getControl(id);
|
2019-03-08 21:22:01 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!control)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.printf_P(PSTR("Error: There is no control with ID %d"), id);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return;
|
2019-03-08 21:22:01 +00:00
|
|
|
}
|
2019-03-26 15:22:21 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
updateControl(control, clientId);
|
2019-03-08 21:22:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateControlValue(Control* control, const String& value, int clientId)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!control)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2019-03-24 14:44:27 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
control->value = value;
|
|
|
|
updateControl(control, clientId);
|
2019-03-08 21:22:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-14 09:59:35 +00:00
|
|
|
void ESPUIClass::updateControlValue(uint16_t id, const String& value, int clientId)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* control = getControl(id);
|
2017-10-19 15:30:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (!control)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.printf_P(PSTR("Error: There is no control with ID %d"), id);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return;
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2019-03-26 15:22:21 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
updateControlValue(control, value, clientId);
|
2017-11-13 15:10:56 +00:00
|
|
|
}
|
2019-03-08 21:22:01 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::print(uint16_t id, const String& value)
|
|
|
|
{
|
|
|
|
updateControlValue(id, value);
|
|
|
|
}
|
2018-12-02 10:41:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateLabel(uint16_t id, const String& value)
|
|
|
|
{
|
|
|
|
updateControlValue(id, value);
|
|
|
|
}
|
2019-03-03 20:46:38 +00:00
|
|
|
|
2022-01-16 14:47:41 +00:00
|
|
|
void ESPUIClass::updateButton(uint16_t id, const String& value) {
|
|
|
|
updateControlValue(id, value);
|
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateSlider(uint16_t id, int nValue, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, String(nValue), clientId);
|
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateSwitcher(uint16_t id, bool nValue, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, String(nValue ? "1" : "0"), clientId);
|
|
|
|
}
|
2017-11-29 10:32:07 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateNumber(uint16_t id, int number, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, String(number), clientId);
|
|
|
|
}
|
2018-11-26 17:25:10 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateText(uint16_t id, const String& text, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, text, clientId);
|
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateSelect(uint16_t id, const String& text, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, text, clientId);
|
|
|
|
}
|
2019-03-04 20:07:39 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::updateGauge(uint16_t id, int number, int clientId)
|
|
|
|
{
|
|
|
|
updateControlValue(id, String(number), clientId);
|
|
|
|
}
|
2019-03-26 15:22:21 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
void ESPUIClass::clearGraph(uint16_t id, int clientId) { }
|
2019-04-15 13:32:14 +00:00
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
Control* control = getControl(id);
|
|
|
|
if (!control)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-04-15 13:32:14 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
String json;
|
|
|
|
DynamicJsonDocument document(jsonUpdateDocumentSize);
|
|
|
|
JsonObject root = document.to<JsonObject>();
|
|
|
|
|
|
|
|
root["type"] = (int)ControlType::GraphPoint;
|
|
|
|
root["value"] = nValue;
|
|
|
|
root["id"] = control->id;
|
|
|
|
serializeJson(document, json);
|
|
|
|
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
|
|
|
{
|
|
|
|
Serial.println(json);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (clientId < 0)
|
|
|
|
{
|
|
|
|
this->ws->textAll(json);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// This is a hacky workaround because ESPAsyncWebServer does not have a
|
|
|
|
// function like this and it's clients array is private
|
|
|
|
int tryId = 0;
|
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
for (size_t count = 0; count < this->ws->count();)
|
2020-09-28 08:40:31 +00:00
|
|
|
{
|
|
|
|
if (this->ws->hasClient(tryId))
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (clientId != tryId)
|
|
|
|
{
|
|
|
|
this->ws->client(tryId)->text(json);
|
|
|
|
|
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
|
|
|
{
|
|
|
|
Serial.println(json);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
count++;
|
2019-04-15 13:32:14 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
tryId++;
|
2019-04-15 13:32:14 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-12 20:12:20 +00:00
|
|
|
|
2018-12-26 11:35:35 +00:00
|
|
|
/*
|
2022-01-12 20:12:20 +00:00
|
|
|
Convert & Transfer Arduino elements to JSON elements. This function sends a chunk of
|
|
|
|
JSON describing the controls of the UI, starting from the control at index startidx.
|
|
|
|
If startidx is 0 then a UI_INITIAL_GUI message will be sent, else a UI_EXTEND_GUI.
|
|
|
|
Both message types contain a list of serialised UI elements. Only a portion of the UI
|
|
|
|
will be sent in order to avoid websocket buffer overflows. The client will acknowledge
|
|
|
|
receipt of a partial message by requesting the next chunk of UI.
|
|
|
|
|
|
|
|
The protocol is:
|
|
|
|
SERVER: jsonDom(0):
|
|
|
|
"UI_INITIAL_GUI: n serialised UI elements"
|
|
|
|
CLIENT: controls.js:handleEvent()
|
|
|
|
"uiok:n"
|
|
|
|
SERVER: jsonDom(n):
|
|
|
|
"UI_EXTEND_GUI: n serialised UI elements"
|
|
|
|
CLIENT: controls.js:handleEvent()
|
|
|
|
"uiok:2*n"
|
|
|
|
etc.
|
2018-12-26 11:35:35 +00:00
|
|
|
*/
|
2022-01-12 20:12:20 +00:00
|
|
|
void ESPUIClass::jsonDom(uint16_t startidx, AsyncWebSocketClient* client)
|
2022-01-02 21:56:32 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
if(startidx >= this->controlCount)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-01-01 22:04:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
DynamicJsonDocument document(jsonInitialDocumentSize);
|
2022-01-12 20:12:20 +00:00
|
|
|
document["type"] = startidx ? (int)UI_EXTEND_GUI : (int)UI_INITIAL_GUI;
|
2020-09-28 08:40:31 +00:00
|
|
|
document["sliderContinuous"] = sliderContinuous;
|
2022-01-12 20:12:20 +00:00
|
|
|
document["startindex"] = startidx;
|
|
|
|
document["totalcontrols"] = this->controlCount;
|
2020-09-28 08:40:31 +00:00
|
|
|
JsonArray items = document.createNestedArray("controls");
|
|
|
|
JsonObject titleItem = items.createNestedObject();
|
|
|
|
titleItem["type"] = (int)UI_TITLE;
|
|
|
|
titleItem["label"] = ui_title;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
prepareJSONChunk(client, startidx, &items);
|
2022-01-01 22:04:32 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
String json;
|
|
|
|
serializeJson(document, json);
|
2022-01-02 21:56:32 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
2022-01-12 20:12:20 +00:00
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
|
|
|
{
|
|
|
|
Serial.println("Sending elements --------->");
|
|
|
|
Serial.println(json);
|
2022-01-01 22:04:32 +00:00
|
|
|
}
|
2022-01-12 20:12:20 +00:00
|
|
|
#endif
|
|
|
|
if (client != nullptr)
|
|
|
|
client->text(json);
|
|
|
|
else
|
|
|
|
this->ws->textAll(json);
|
2022-01-01 22:04:32 +00:00
|
|
|
}
|
|
|
|
|
2022-01-02 21:56:32 +00:00
|
|
|
/* Prepare a chunk of elements as a single JSON string. If the allowed number of elements is greater than the total
|
2022-01-12 20:12:20 +00:00
|
|
|
number this will represent the entire UI. More likely, it will represent a small section of the UI to be sent. The client
|
|
|
|
will acknoledge receipt by requesting the next chunk. */
|
|
|
|
void ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, uint16_t startindex, JsonArray* items)
|
2022-01-02 21:56:32 +00:00
|
|
|
{
|
2022-01-12 20:12:20 +00:00
|
|
|
//First check that there will be sufficient nodes in the list
|
|
|
|
if(startindex >= this->controlCount)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Follow the list until control points to the startindex'th node
|
|
|
|
Control* control = this->controls;
|
|
|
|
for(auto i = 0; i < startindex; i++) {
|
|
|
|
control = control->next;
|
|
|
|
}
|
2022-01-01 22:04:32 +00:00
|
|
|
|
2022-01-12 20:12:20 +00:00
|
|
|
//To prevent overflow, keep track of the number of elements we have serialised into this message
|
|
|
|
int elementcount = 0;
|
2022-01-02 21:56:32 +00:00
|
|
|
while (control != nullptr && elementcount < 10)
|
|
|
|
{
|
2022-01-01 22:04:32 +00:00
|
|
|
JsonObject item = items->createNestedObject();
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
item["id"] = String(control->id);
|
|
|
|
item["type"] = (int)control->type;
|
|
|
|
item["label"] = control->label;
|
|
|
|
item["value"] = String(control->value);
|
|
|
|
item["color"] = (int)control->color;
|
2021-10-29 17:47:46 +00:00
|
|
|
item["visible"] = (int)control->visible;
|
2022-01-02 21:56:32 +00:00
|
|
|
if (control->panelStyle != 0)
|
|
|
|
item["panelStyle"] = String(control->panelStyle);
|
|
|
|
if (control->elementStyle != 0)
|
|
|
|
item["elementStyle"] = String(control->elementStyle);
|
2022-01-08 21:25:10 +00:00
|
|
|
if (control->wide == true)
|
|
|
|
item["wide"] = true;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2022-01-02 21:56:32 +00:00
|
|
|
if (control->parentControl != Control::noParent)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
item["parentControl"] = String(control->parentControl);
|
|
|
|
}
|
2019-03-03 22:22:01 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// special case for selects: to preselect an option, you have to add
|
|
|
|
// "selected" to <option>
|
2022-01-02 21:56:32 +00:00
|
|
|
if (control->type == ControlType::Option)
|
|
|
|
{
|
|
|
|
if (ESPUI.getControl(control->parentControl)->value == control->value)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
item["selected"] = "selected";
|
|
|
|
}
|
2022-01-02 21:56:32 +00:00
|
|
|
else
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
item["selected"] = "";
|
|
|
|
}
|
|
|
|
}
|
2019-03-05 23:18:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
control = control->next;
|
2022-01-01 22:04:32 +00:00
|
|
|
elementcount++;
|
2020-09-28 08:40:31 +00:00
|
|
|
}
|
2022-01-12 20:12:20 +00:00
|
|
|
return;
|
2018-12-26 12:38:38 +00:00
|
|
|
}
|
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
void ESPUIClass::jsonReload()
|
2020-06-15 09:06:34 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
String json;
|
|
|
|
DynamicJsonDocument document(jsonUpdateDocumentSize);
|
|
|
|
JsonObject root = document.to<JsonObject>();
|
2020-06-15 09:06:34 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
root["type"] = (int)UI_RELOAD;
|
|
|
|
serializeJson(document, json);
|
2020-06-15 09:06:34 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity >= Verbosity::VerboseJSON)
|
|
|
|
{
|
|
|
|
Serial.println(json);
|
|
|
|
}
|
|
|
|
#endif
|
2020-06-15 09:06:34 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
this->ws->textAll(json);
|
2020-06-15 09:06:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const char* password, uint16_t port)
|
2022-01-04 10:35:43 +00:00
|
|
|
{
|
|
|
|
// Backwards compatibility wrapper
|
|
|
|
beginLITTLEFS(_title, username, password, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const char* password, uint16_t port)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-10-18 09:06:38 +00:00
|
|
|
ui_title = _title;
|
|
|
|
this->basicAuthUsername = username;
|
|
|
|
this->basicAuthPassword = password;
|
2020-09-27 11:20:14 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
if (username == nullptr && password == nullptr)
|
|
|
|
{
|
|
|
|
basicAuth = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
basicAuth = true;
|
|
|
|
}
|
2020-09-27 11:20:14 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
server = new AsyncWebServer(port);
|
2020-10-18 09:06:38 +00:00
|
|
|
ws = new AsyncWebSocket("/ws");
|
2020-09-28 08:40:31 +00:00
|
|
|
|
2020-09-27 11:20:14 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
bool fsBegin = LITTLEFS.begin();
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
bool fsBegin = LittleFS.begin();
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2021-10-29 17:20:20 +00:00
|
|
|
if (!fsBegin)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
2022-01-04 10:35:43 +00:00
|
|
|
Serial.println(F("LITTLEFS Mount Failed, PLEASE CHECK THE README ON HOW TO "
|
2020-09-28 08:40:31 +00:00
|
|
|
"PREPARE YOUR ESP!!!!!!!"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
2020-06-23 18:34:05 +00:00
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
listDir("/", 1);
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2020-09-28 08:40:31 +00:00
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-10-18 09:06:38 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
bool indexExists = LITTLEFS.exists("/index.htm");
|
2020-10-18 09:06:38 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
bool indexExists = LittleFS.exists("/index.htm");
|
2020-10-18 09:06:38 +00:00
|
|
|
#endif
|
2021-10-29 17:20:20 +00:00
|
|
|
if (!indexExists)
|
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (ESPUI.verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("Please read the README!!!!!!!, Make sure to "
|
|
|
|
"ESPUI.prepareFileSystem() once in an empty sketch"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2017-11-29 13:36:19 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
ws->onEvent(onWsEvent);
|
|
|
|
server->addHandler(ws);
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (basicAuth)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
if (WS_AUTHENTICATION)
|
|
|
|
{
|
|
|
|
ws->setAuthentication(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword);
|
|
|
|
}
|
2020-09-27 11:20:14 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
server->serveStatic("/", LITTLEFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2021-10-29 17:20:20 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-27 11:20:14 +00:00
|
|
|
#if defined(ESP32)
|
2022-01-04 10:35:43 +00:00
|
|
|
server->serveStatic("/", LITTLEFS, "/").setDefaultFile("index.htm");
|
2020-09-27 11:20:14 +00:00
|
|
|
#else
|
2021-10-29 17:20:20 +00:00
|
|
|
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm");
|
2020-09-27 11:20:14 +00:00
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// Heap for general Servertest
|
|
|
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
|
|
|
|
2022-01-04 10:35:43 +00:00
|
|
|
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In LITTLEFS mode");
|
2020-09-28 08:40:31 +00:00
|
|
|
});
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->onNotFound([](AsyncWebServerRequest* request) { request->send(404); });
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->begin();
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("UI Initialized"));
|
|
|
|
}
|
|
|
|
#endif
|
2018-12-26 12:38:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
void ESPUIClass::begin(const char* _title, const char* username, const char* password, uint16_t port)
|
2020-06-23 18:34:05 +00:00
|
|
|
{
|
2020-09-28 08:40:31 +00:00
|
|
|
basicAuthUsername = username;
|
|
|
|
basicAuthPassword = password;
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (username != nullptr && password != nullptr)
|
|
|
|
{
|
|
|
|
basicAuth = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
basicAuth = false;
|
|
|
|
}
|
2018-12-26 12:38:38 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
ui_title = _title;
|
2018-12-26 12:38:38 +00:00
|
|
|
|
2021-10-29 17:20:20 +00:00
|
|
|
server = new AsyncWebServer(port);
|
2020-09-28 08:40:31 +00:00
|
|
|
ws = new AsyncWebSocket("/ws");
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
ws->onEvent(onWsEvent);
|
|
|
|
server->addHandler(ws);
|
2018-12-26 12:38:38 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
if (basicAuth && WS_AUTHENTICATION)
|
|
|
|
ws->setAuthentication(username, password);
|
2018-12-26 12:38:38 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", HTML_INDEX);
|
|
|
|
request->send(response);
|
|
|
|
});
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// Javascript files
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/js/zepto.min.js", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "application/javascript", JS_ZEPTO_GZIP, sizeof(JS_ZEPTO_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/js/controls.js", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "application/javascript", JS_CONTROLS_GZIP, sizeof(JS_CONTROLS_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2019-03-24 14:44:27 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/js/slider.js", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 21:21:21 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "application/javascript", JS_SLIDER_GZIP, sizeof(JS_SLIDER_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2019-04-15 11:49:15 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/js/graph.js", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-04-15 11:49:15 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "application/javascript", JS_GRAPH_GZIP, sizeof(JS_GRAPH_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2019-03-24 14:44:27 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/js/tabbedcontent.js", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-24 17:10:21 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response = request->beginResponse_P(
|
|
|
|
200, "application/javascript", JS_TABBEDCONTENT_GZIP, sizeof(JS_TABBEDCONTENT_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2019-03-03 21:21:21 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// Stylesheets
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/css/style.css", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "text/css", CSS_STYLE_GZIP, sizeof(CSS_STYLE_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->on("/css/normalize.css", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
AsyncWebServerResponse* response
|
|
|
|
= request->beginResponse_P(200, "text/css", CSS_NORMALIZE_GZIP, sizeof(CSS_NORMALIZE_GZIP));
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
request->send(response);
|
|
|
|
});
|
2018-05-27 08:35:37 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
// Heap for general Servertest
|
|
|
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest* request) {
|
|
|
|
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
|
|
|
|
{
|
|
|
|
return request->requestAuthentication();
|
|
|
|
}
|
2019-03-03 20:13:45 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In Memorymode");
|
|
|
|
});
|
2017-10-16 13:00:53 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->onNotFound([](AsyncWebServerRequest* request) { request->send(404); });
|
2017-10-16 13:00:53 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
server->begin();
|
2017-05-18 22:05:32 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
#if defined(DEBUG_ESPUI)
|
|
|
|
if (this->verbosity)
|
|
|
|
{
|
|
|
|
Serial.println(F("UI Initialized"));
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-03 20:13:45 +00:00
|
|
|
}
|
2019-03-24 15:06:35 +00:00
|
|
|
|
2020-09-28 08:40:31 +00:00
|
|
|
void ESPUIClass::setVerbosity(Verbosity v)
|
|
|
|
{
|
|
|
|
this->verbosity = v;
|
|
|
|
}
|
2019-03-24 15:06:35 +00:00
|
|
|
|
2020-06-23 18:34:05 +00:00
|
|
|
ESPUIClass ESPUI;
|