From ea8de922461583fc2e1e16c276d7c1b175bb7f47 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 6 Feb 2024 22:38:17 -0500 Subject: [PATCH 01/14] Checkpoint adding fileDisplay object --- data/js/controls.js | 69 +++++++++++++++++++++++++-------- pio_examples/gui/platformio.ini | 6 +++ pio_examples/gui/src/gui.ino | 22 +++++++++-- src/ESPUI.cpp | 13 +++++++ src/ESPUI.h | 1 + src/ESPUIcontrol.cpp | 1 + src/ESPUIcontrol.h | 4 +- 7 files changed, 95 insertions(+), 21 deletions(-) diff --git a/data/js/controls.js b/data/js/controls.js index 84b001b..da9303c 100644 --- a/data/js/controls.js +++ b/data/js/controls.js @@ -60,7 +60,10 @@ const UPDATE_SEPARATOR = 119; const UI_TIME = 20; const UPDATE_TIME = 120; -const UI_FRAGMENT = 21; +const UI_FILEDISPLAY = 21; +const UPDATE_FILEDISPLAY = 121; + +const UI_FRAGMENT = 98; const UP = 0; const DOWN = 1; @@ -80,7 +83,7 @@ const C_DARK = 7; const C_NONE = 255; var controlAssemblyArray = new Object(); -var FragmentAssemblyTimer = new Object(); +var FragmentAssemblyTimer = new Array(); var graphData = new Array(); var hasAccel = false; var sliderContinuous = false; @@ -197,8 +200,8 @@ function conStatusError() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); if (true === websockConnected) { websockConnected = false; @@ -220,10 +223,10 @@ function handleVisibilityChange() { } function start() { - let location = window.location.hostname; - let port = window.location.port; -// let location = "192.168.10.229"; -// let port = ""; +// let location = window.location.hostname; +// let port = window.location.port; + let location = "192.168.10.219"; + let port = ""; document.addEventListener("visibilitychange", handleVisibilityChange, false); if ( @@ -257,8 +260,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; websock.onclose = function (evt) { @@ -270,8 +273,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; websock.onerror = function (evt) { @@ -283,8 +286,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; var handleEvent = function (evt) { @@ -367,7 +370,7 @@ function start() { if (data.visible) addToHTML(data); break; - /* + /* These elements must call additional functions after being added to the DOM */ case UI_BUTTON: @@ -565,6 +568,14 @@ function start() { } break; + case UI_FILEDISPLAY: + if (data.visible) + { + addToHTML(data); + FileDisplayUploadFile(data); + } + break; + /* * Update messages change the value/style of a component without adding new HTML */ @@ -639,6 +650,10 @@ function start() { websock.send("time:" + rv + ":" + data.id); break; + case UPDATE_FILEDISPLAY: + FileDisplayUploadFile(data); + break; + case UI_FRAGMENT: let FragmentLen = data.length; let FragementOffset = data.offset; @@ -770,6 +785,25 @@ function start() { websock.onmessage = handleEvent; } +function FileDisplayUploadFile(data) +{ + let text = downloadFile(data.value); + // populate the text object +} // FileDisplayUploadFile + +async function downloadFile(filename) { + let response = await fetch(filename); + + if(response.status != 200) { + throw new Error("File Read Server Error: '" + response.status + "'"); + } + + // read response stream as text + let text_data = await response.text(); + + return text_data; +} // downloadFile + function StartFragmentAssemblyTimer(Id) { StopFragmentAssemblyTimer(Id); @@ -930,6 +964,7 @@ var addToHTML = function (data) { case UI_GRAPH: case UI_GAUGE: case UI_ACCEL: + case UI_FILEDISPLAY: html = "
" + data.label + "

" + elementHTML(data) + @@ -1020,8 +1055,6 @@ var elementHTML = function (data) { } } - - var processEnabled = function (data) { //Handle the enabling and disabling of controls //Most controls can be disabled through the use of $("#").prop("disabled", true) and CSS will style it accordingly @@ -1067,6 +1100,8 @@ var processEnabled = function (data) { case UI_CPAD: case UPDATE_PAD: case UPDATE_CPAD: + case UI_FILEDISPLAY: + case UPDATE_FILEDISPLAY: if (data.enabled) { $("#id" + data.id + " nav").removeClass('disabled'); } else { diff --git a/pio_examples/gui/platformio.ini b/pio_examples/gui/platformio.ini index 62f30c8..c1c0632 100644 --- a/pio_examples/gui/platformio.ini +++ b/pio_examples/gui/platformio.ini @@ -32,6 +32,9 @@ lib_ignore = [env:esp8266] platform = espressif8266 board = nodemcuv2 +upload_port = COM8 +monitor_port = COM8 +monitor_speed = 115200 [env:esp32] platform = espressif32 @@ -41,3 +44,6 @@ board_build.flash_mode = dout lib_deps = ${env.lib_deps} me-no-dev/AsyncTCP +upload_port = COM9 +monitor_port = COM9 +monitor_speed = 115200 diff --git a/pio_examples/gui/src/gui.ino b/pio_examples/gui/src/gui.ino index 2fd6460..8bcff6c 100644 --- a/pio_examples/gui/src/gui.ino +++ b/pio_examples/gui/src/gui.ino @@ -11,8 +11,8 @@ DNSServer dnsServer; #include #endif -const char* ssid = "ESPUI"; -const char* password = "espui"; +const char* ssid = "MaRtInG"; +const char* password = "martinshomenetwork"; const char* hostname = "espui"; @@ -238,6 +238,7 @@ void setup(void) ESPUI.slider("Slider two", &slider, ControlColor::None, 100); ESPUI.text("Text Test:", &textCall, ControlColor::Alizarin, "a Text Field"); ESPUI.number("Numbertest", &numberCall, ControlColor::Alizarin, 5, 0, 10); + ESPUI.fileDisplay("Filetest", ControlColor::Turquoise, "DisplayFile.txt"); graphId = ESPUI.graph("Graph Test", ControlColor::Wetasphalt); @@ -258,7 +259,22 @@ void setup(void) * password, for example begin("ESPUI Control", "username", "password") */ ESPUI.sliderContinuous = true; - ESPUI.begin("ESPUI Control"); + ESPUI.beginLITTLEFS("ESPUI Control"); + + // create a text file + ESPUI.prepareFileSystem(); + #if defined(ESP32) +#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION_MINOR >= 4) || ESP_IDF_VERSION_MAJOR > 4 + File testFile = LittleFS.open("/DisplayFile.txt", "w"); +#else + File testFile = LITTLEFS.open("/DisplayFile.txt", "w"); +#endif +#else + File testFile = LittleFS.open("/DisplayFile.txt", "w"); +#endif + String TestLine = "Test Line\n"; + testFile.write((const uint8_t*)TestLine.c_str(), TestLine.length()); + testFile.close(); } void loop(void) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 8fdb806..c2f3565 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -805,6 +805,11 @@ uint16_t ESPUIClass::separator(const char* label) return addControl(ControlType::Separator, label, "", ControlColor::Alizarin, Control::noParent, nullptr); } +uint16_t ESPUIClass::fileDisplay(const char* label, ControlColor color, String filename) +{ + return addControl(ControlType::FileDisplay, label, filename, color, Control::noParent); +} + uint16_t ESPUIClass::accelerometer(const char* label, std::function callback, ControlColor color) { return addControl(ControlType::Accel, label, "", color, Control::noParent, callback); @@ -1425,6 +1430,14 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas server->onNotFound([this](AsyncWebServerRequest* request) { if (captivePortal) { + AsyncResponseStream *response = request->beginResponseStream("text/html"); + String responseText; + responseText.reserve(1024); + responseText += F("Captive Portal"); + responseText += ("

If site does not re-direct click here this link

"); + responseText += (""); + response->write(responseText.c_str(), responseText.length()); + request->send(response); request->redirect("/"); } else diff --git a/src/ESPUI.h b/src/ESPUI.h index 23d65ad..ceb4748 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -143,6 +143,7 @@ public: uint16_t gauge(const char* label, ControlColor color, int value, int min = 0, int max = 100); // Create Gauge display uint16_t separator(const char* label); //Create separator + uint16_t fileDisplay(const char* label, ControlColor color, String filename); // Input only uint16_t accelerometer(const char* label, std::function callback, ControlColor color); diff --git a/src/ESPUIcontrol.cpp b/src/ESPUIcontrol.cpp index 75606de..44002ac 100644 --- a/src/ESPUIcontrol.cpp +++ b/src/ESPUIcontrol.cpp @@ -280,3 +280,4 @@ void Control::onWsEvent(String & cmd, String& data) } } while (false); } + diff --git a/src/ESPUIcontrol.h b/src/ESPUIcontrol.h index 194d697..d075353 100644 --- a/src/ESPUIcontrol.h +++ b/src/ESPUIcontrol.h @@ -30,8 +30,9 @@ enum ControlType : uint8_t Accel, Separator, Time, + FileDisplay, - Fragment, + Fragment = 98, Password = 99, UpdateOffset = 100, }; @@ -93,6 +94,7 @@ public: private: bool _ToBeDeleted = false; uint32_t ControlChangeID = 0; + String OldValue = emptyString; }; #define UI_TITLE ControlType::Title From d2ccf8387478988ed3a0af67546bdfcaeb43ac15 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 10 Feb 2024 13:52:06 -0500 Subject: [PATCH 02/14] Changes to support processing a file to display --- data/js/controls.js | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/data/js/controls.js b/data/js/controls.js index da9303c..908dd1a 100644 --- a/data/js/controls.js +++ b/data/js/controls.js @@ -223,10 +223,10 @@ function handleVisibilityChange() { } function start() { -// let location = window.location.hostname; -// let port = window.location.port; - let location = "192.168.10.219"; - let port = ""; + let location = window.location.hostname; + let port = window.location.port; +// let location = "192.168.10.219"; +// let port = ""; document.addEventListener("visibilitychange", handleVisibilityChange, false); if ( @@ -785,14 +785,29 @@ function start() { websock.onmessage = handleEvent; } -function FileDisplayUploadFile(data) +async function FileDisplayUploadFile(data) { - let text = downloadFile(data.value); + let text = await downloadFile(data.value); + let ItemToUpdateId = "fd" + data.id; + // console.info("ItemToUpdateId: " + ItemToUpdateId); + // console.info(" text: " + text); // populate the text object + $("#" + ItemToUpdateId).val(text); + $("#" + ItemToUpdateId).css("textAlign", "left"); + $("#" + ItemToUpdateId).css("white-space", "nowrap"); + $("#" + ItemToUpdateId).css("overflow", "scroll"); + $("#" + ItemToUpdateId).css("overflow-y", "scroll"); + $("#" + ItemToUpdateId).css("overflow-x", "scroll"); + $("#" + ItemToUpdateId).scrollTop($("#" + ItemToUpdateId).val().length); + + // scroll the page to the updated control + // $("#" + ItemToUpdateId).focus(); + } // FileDisplayUploadFile -async function downloadFile(filename) { - let response = await fetch(filename); +async function downloadFile(filename) +{ + let response = await fetch(filename); if(response.status != 200) { throw new Error("File Read Server Error: '" + response.status + "'"); @@ -970,6 +985,7 @@ var addToHTML = function (data) { elementHTML(data) + "
"; break; + case UI_SEPARATOR: html = "
" + "
" + data.label + "

"; @@ -996,6 +1012,9 @@ var elementHTML = function (data) { case UI_LABEL: return "" + data.value + ""; + case UI_FILEDISPLAY: + return ""; case UI_BUTTON: return "";case UI_SWITCHER:return"