Code Monkey home page Code Monkey logo

espui's Introduction

ESPUI

ESPUI

ESPUI is a simple library to make a web-based user interface for your projects using the ESP8266 or the ESP32 It uses web sockets and lets you create,

ol, and update elements on your GUI through multiple devices like phones and tablets.

ESPUI uses simple Arduino-style syntax for creating a solid, functioning user interface without too much boilerplate code.

So if you either don't know how or just don't want to waste time: this is your simple solution user interface without the need of internet connectivity or any additional servers.

The Library runs on any kind of ESP8266 and ESP32 (NodeMCU, AI Thinker, etc.).

Contributed features

  • Tabs by @eringerli
  • Generic API by @eringerli
  • Min Max on slider by @eringerli
  • OptionList by @eringerli
  • Public Access to ESPAsyncServer
  • Inline CSS styles by @iangray001
  • Separators by @iangray001
  • Grouped and wide controls by @iangray001
  • Transport layer rework by @iangray001
  • Time control by @iangray001
  • Vertical controls by @iangray001
  • Time/date/password/color input types by @pcbbc
  • Delayed response support @MartinMueller2003
  • Fragmented control transfer @MartinMueller2003
  • Extended Callback @MartinMueller2003
  • Added a file display element @MartinMueller2003

Roadmap

  • Fully implement graphs
  • Expand number input features (floats etc.)
  • Support for enabling and disabling controls

Dependencies

This library is dependent on the following libraries.

How to Install

Make sure all the dependencies are installed, then install like so:

Using PlatformIO (recommended)

Just include this library as a dependency in lib_deps like so:

lib_deps =
    ESPUI
    ESP Async WebServer
    ESPAsyncTCP # (or AsyncTCP on ESP32)
    LittleFS_esp32 # (ESP32 only)

Using the Arduino IDE (recommended)

You can find this Library in the Arduino IDE library manager. Go to Sketch > Include Library > Library Manager search for ESPUI and install.

If you cannot use the Library Manager, you can download the repository and follow the instructions to manually install libraries.

Getting started

ESPUI serves several files to the browser to build up its web interface. This can be achieved in 2 ways: PROGMEM or LITTLEFS

When ESPUI.begin() is called the default is serving files from Memory and ESPUI should work out of the box!

OPTIONAL: But if this causes your program to use too much memory you can burn the files into the LITTLEFS filesystem on the ESP. There are now two ways to do this: you can either use the ESP file upload tool or you use the library function ESPUI.prepareFileSystem()

Simple filesystem preparation (recommended)

Just open the example sketch prepareFileSystem and run it on the ESP, (give it up to 30 seconds, you can see the status on the Serial Monitor), The library will create all needed files. Congratulations, you are done, from now on you just need to do this again when there is a library update, or when you want to use another chip :-) Now you can upload your normal sketch, when you do not call the ESPUI.prepareFileSystem() function the compiler will strip out all the unnecessary strings that are already saved in the chip's filesystem and you have more program memory to work with.

User interface Elements

  • Label
  • Button
  • Switch
  • Control pad
  • Slider
  • Text Input
  • Date, Time, Colour and Password Input
  • Numberinput
  • Option select
  • Separator
  • Time
  • Graph (partial implementation)
  • File Display

Documentation

The heart of ESPUI is ESPAsyncWebserver. ESPUI's frontend is based on Skeleton CSS and jQuery-like lightweight zepto.js for handling events. The communication between the ESP and the client browser works using web sockets. ESPUI does not need network access and can be used in standalone access point mode, all resources are loaded directly from the ESPs memory.

This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino setup() routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object ESPUI. Eg: ESPUI.button("button", &myCallback); creates a button in the interface that calls the myCallback(Control *sender, int eventname) function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events, an integer number with the event name is passed to the callback function that can be handled in a switch(){}case{} statement.

Alternativly you may use the extended callback funtion which provides three parameters to the callback function myCallback(Control *sender, int eventname, void * UserParameter). The UserParameter is provided as part of the ESPUI.addControl method set and allows the user to define contextual information that is to be presented to the callback function in an unmodified form.

It also possible to use a lambda function in the callback parameter. It also allows the user to define, in a more C++ way, contextual information in any form. This is shown by the completeLambda example.

The below example creates a button and defines a lambda function to invoke a more specialized button callback handler:

void YourClassName::setup()
{
  ButtonElementId = ESPUI.addControl(
  ControlType::Button,
  ButtonLabel.c_str(),
  " Button Face Text ",
  ControlColor::None,
  ParentElementId,
  [&](Control *sender, int eventname)
  {
    myButtonCallback(sender, eventname); // class method
  });

  // or
  ButtonElementId = ESPUI.button(
  " Button Face Text ",
  [&](Control *sender, int eventname)
  {
    myButtonCallback(sender, eventname); // class method
  });
}
void YourClassName::myButtonCallback(Control* sender, int eventname)
{
  if (eventname == B_DOWN)
  {
    // Handle the button down event
  }
  else if (eventname == B_UP)
  {
    // Handle the button up event
  }
}


#### Button

Buttons

Buttons have a name and a callback value. Their text can be changed at runtime using ESPUI.updateButton().

Events:

  • B_DOWN - Fired when button is pressed.
  • B_UP - Fired when button is released.

Switch

Switches

Switches sync their state on all connected devices. This means when you change their value (either by pressing them, or programmatically using ESPUI.updateSwitcher()) they change visibly on all tablets or computers that currently display the interface.

Events:

  • S_ACTIVE - Fired when turning on.
  • S_INACTIVE - Fired when turning off.

Buttonpad

control pads

Button pads come in two flavours: with or without a center button. They are useful for controlling movements of vehicles/cameras etc. They use a single callback per pad and have 8 or 10 different event types to differentiate the button actions.

  • P_LEFT_DOWN
  • P_LEFT_UP
  • P_RIGHT_DOWN
  • P_RIGHT_UP
  • P_FOR_DOWN
  • P_FOR_UP
  • P_BACK_DOWN
  • P_BACK_UP
  • P_CENTER_DOWN
  • P_CENTER_UP

Labels

labels

Labels are used to display textual information (i.e. states, values of sensors, configuration parameters etc.). To send data from the code use ESP.updateLabel() . Labels get a name on creation and a initial value.

Labels automatically wrap your text. If you want them to have multiple lines use the normal <br> tag in the string you print to the label.

In fact, because HTML can be used in the label's value, you can make a label display images by including an <img> tag.

 ESPUI.label("An Image Label", ControlColor::Peterriver, "<img src='path/to/image'>");

This requires that the client has access to the image in question, either from the internet or a local web server.

Slider

slider

Sliders can be used to select (or display) a numerical value. Sliders provide realtime data and are touch compatible. Note that like all ESPUI functions, the callback does not return an int but a String so should be converted with the .toInt() function. See the examples for more details. Sliders can be updated from code using ESP.updateSlider().

A slider usually only sends a new value when it is released to save network bandwidth. This behaviour can be changed globally by setting sliderContinuous before begin():

ESPUI.sliderContinuous = true;
ESPUI.begin("ESPUI Control");

Events:

  • SL_VALUE - Fired when a slider value changes.

Number Input

number

The number input can be used to receive numbers from the user. You can enter a value into it and when you are done with your change it is sent to the ESP. A number box needs to have a min and a max value. To set it up just use:

ESPUI.number("Numbertest", &numberCall, ControlColor::Alizarin, 5, 0, 10);

Number inputs can be updated from code using ESP.updateNumber().

Note that HTML number boxes will respect their min and max when the user clicks the up and down arrows, but it is possible on most clients to simply type any number in. As with all user input, numbers should be validated in callback code because all client side checks can be skipped. If any value from the UI might cause a problem, validate it.

Events:

  • N_VALUE - Fired when a number value changes.

Text Input

text

The text input works very similar like the number input but allows any string to be entered. If you attach a Max control to the text input then a max length will be applied to the control.

text = ESPUI.text("Label", callback, ControlColor::Dark, "Initial value");
ESPUI.addControl(ControlType::Max, "", "32", ControlColor::None, text);

Text inputs can be updated from code using ESP.updateText().

However even with a set maximum length, user input should still be validated because it is easy to bypass client-side checks. Never trust user input.

Events:

  • T_VALUE - Fired when a text value changes.

Date, Time, Colour and Password Input

text

As an extension to the text input control, you can also specify the type attribute to be used for the HTML input element. This allows you to easily create input controls for Date, Time, Colour and Passwords, or indeed any other HTML Input Types supported by your browser.

text_date = ESPUI.text("Date", callback, ControlColor::Dark, "2022-05-24");
ESPUI.setInputType(text_date, "date");

text_time = ESPUI.text("Time", callback, ControlColor::Dark, "13:00");
ESPUI.setInputType(text_time, "time");

text_colour = ESPUI.text("Colour", callback, ControlColor::Dark, "#FF0000");
ESPUI.setInputType(text_colour, "color");

text_password = ESPUI.text("Password", callback, ControlColor::Dark, "tiddles123");
ESPUI.setInputType(text_password, "password");

Important! This function should be called before ESPUI.begin or results will be unreliable.

Note that not all browsers support all input types, and that the control displayed to edit the input is browser dependent.

However even with a type set, user input should still be validated because it is easy to bypass client-side checks. Never trust user input.

File Display

filedisplay

The File Display control is used to upload a file from the ESP file system and display the contents on the UI. The content is Auto Scrolled to the last line in the file. Syntax:

fileDisplayId = ESPUI.fileDisplay("Filetest", ControlColor::Turquoise, FullyQualified FilePath);

After updating the contents of the file, trigger a display update using: ESPUI.updateControl(fileDisplayId);

Select control

option1 option2

The Select control lets the user select from a predefined list of options. First create a select widget like so

uint16_t select1 = ESPUI.addControl( ControlType::Select, "Select Title", "Initial Value", ControlColor::Alizarin, tab1, &selectExample );

Then add Options to it, specifying the Select as the parent:

ESPUI.addControl( ControlType::Option, "Option1", "Opt1", ControlColor::Alizarin, select1);
ESPUI.addControl( ControlType::Option, "Option2", "Opt2", ControlColor::Alizarin, select1);
ESPUI.addControl( ControlType::Option, "Option3", "Opt3", ControlColor::Alizarin, select1);

Check the tabbedGui example for a working demo. Selectors can be updated from code using ESP.updateSelect().

Events:

  • S_VALUE - Fired when a select value changes.

Getting the Time

ESPUI can create an invisible control that can be used to fetch the current time from the client when they are connected to the UI. This could be used to intermittently provide an accurate time source to your ESP. Remember that clients cannot be relied upon to be correct or truthful.

Create a Time control with the following:

//Add the invisible "Time" control
auto timeId = ESPUI.addControl(Time, "", "", None, 0, timeCallback);

After creating the UI, sending an update to the Time control will cause it to fetch the current time from the client and then fire its callback with the result.

//Request an update to the time
ESPUI.updateTime(timeId);
//Will trigger timeCallback

In timeCallback you can then print the control's value as normal:

void timeCallback(Control *sender, int type) {
  if(type == TM_VALUE) { 
    Serial.println(sender->value);
  }
}

The returned string will be an ISO string as returned by the Javascript new Date().toISOString(). The format is YYYY-MM-DDTHH:mm:ss.sssZ so for example: 2022-01-20T21:44:22.913Z.

Events:

  • TM_VALUE - Fires when the control is updated with updateTime()

Separators

separators

You can use separators to break up the UI and better organise your controls. Adding a separator will force any following controls onto the subsequent line. Add separators as follows:

ESPUI.separator("Separator name");
//or
ESPUI.addControl(ControlType::Separator, "Separator name", "", ControlColor::None, maintab);

Separators fire no events.

Initialisation of the UI

After all the elements are configured, call ESPUI.begin("Some Title"); to start the UI interface. (Or ESPUI.beginLITTLEFS("Some Title"); respectively) Make sure you setup a working network connection or AccessPoint before (see the gui.ino example). The web interface can then be used from multiple devices at once and also shows connection status in the top bar.

Tabs

tabs

Tabs can be used to organize your controls into pages. Check the tabbedGui example to see how this is done. Tabs can be created as follows:

ESPUI.addControl(ControlType::Tab, "Settings 1", "Settings 1");

Then all widgets for the tab need to be added to it by specifying the tab as the parent. Widgets not added to a tab will be shown above the tab selctor.

ESPUI.addControl(ControlType::Text, "Text Title", "a Text Field", ControlColor::Alizarin, tab1, &textCall);

Note that the basic functions to add controls like ESPUI.button() or ESPUI.slider() do not add to any tab, so they are good for building small UIs. However if you need to use tabs then you will have to add all your controls using the full ESPUI.addControl() function.

Log output

ESPUI has several different log levels. You can set them using the ESPUI.setVerbosity(Verbosity::VerboseJSON) function.

Loglevels are:

  • Verbosity::Quiet (default)
  • Verbosity::Verbose
  • Verbosity::VerboseJSON

VerboseJSON outputs the most debug information.

Colours

A selection of basic colours are available to use:

Colours

If you want more control over the UI design, see the Inline Styles section below.

Advanced Features

ESPUI includes a range of advanced features that can customise your UIs.

Dynamic Visibility

Controls can be made visible or invisible at runtime with the updateVisibility() function.

ESPUI.updateVisibility(controlId, false);

Note that you cannot hide individual controls from a control group, you have to hide the entire group.

Inline Styles

You can add custom CSS styles to controls. This allows you to style the UI with custom colors, drop shadows, or other CSS effects. Add styles with the following functions:

setPanelStyle(uint16_t id, String style);
setElementStyle(uint16_t id, String style)

A panel style is applied to the panel on which the UI element is placed, an element style is applied to the element itself. Because CSS inline styles can only style one specific DOM element, for controls made up of multiple elements (like the pad) this is limited. Element styles can be applied to all controls, but will only work correctly for the Button, Label, Slider, Switcher, Number, Text, and Selector.

Dynamic update of styles is supported. When either of the above functions are called, the control is updated live. This could be used to refect a warning state by changing the color of a button, or for similar effects.

For example, this code will set a control's panel to a random background color:

char stylecol[30];
sprintf(stylecol, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
ESPUI.setPanelStyle(switch1, stylecol);

You can get quite creative with this.

Inline Styles

The completeExample example includes a range of things that you can do with inline styles.

More Inline Styles

Disabling Controls

It is possible to dynamically enable and disable controls to, for example, provide feedback to the user that a particular feature is temporarily unavailable. To do this use the following function call:

ESPUI.setEnabled(controlId, enabled);

Setting enabled to false will make the control noninteractive and it will visually change to illustrate this to the user. The control will stop firing any events. Note that whilst the widget will change appearance, the panel of the control will remain whatever colour it was set to. If you wish to also change the colour of the panel then you should use inline styles to show the noninteractive state. For example:

ESPUI.setEnabled(mainButton, false);
const String disabledstyle = "background-color: #bbb; border-bottom: #999 3px solid;";
ESPUI.setPanelStyle(mainButton, disabledstyle);

This CSS style sets the panel background and its border to grey. To put the control back to enabled use the following:

ESPUI.setEnabled(mainButton, true);
ESPUI.setPanelStyle(mainButton, ";");

Note that we have to set the inline style to ";" (i.e. an empty CSS rule) because if we just try to set it to "" this will be interpreted as "do not change the style".

Controls can also be set to disabled before the UI is started.

Grouped controls

Normally, whenever a control is added to the UI, a new panel is generated with a title. However, you can instead set the "parent" of a new control to be an existing control. This allows you to add multiple widgets into the same panel. For example:

panel1 = ESPUI.addControl(ControlType::Button, "Button Set", "Button A", ControlColor::Turquoise, Control::noParent, btncallback);
ESPUI.addControl(ControlType::Button, "", "Button B", ControlColor::None, panel1, btncallback);
ESPUI.addControl(ControlType::Button, "", "Button C", ControlColor::None, panel1, btncallback);

The first call to addControl has no parent (or it could be set to a tab if you are using a tabbed UI), so therefore a new panel is added containing one button with the value Button A. The two subsequent calls have their parent set to the first control we added, so instead of creating a new panel, the result is the following:

Grouped buttons

The grouped controls operate entirely independently, and can be assigned different callbacks, or updated separately. The grouping is purely visual.

Most controls can be grouped this way, but the result is not always visually pleasant. This works best with labels, sliders, switchers, and buttons.

Other grouped controls

For sliders and switchers, you can also set the controls to be displayed vertically.

auto vertswitcher = ESPUI.addControl(Switcher, "Vertical Switcher", "0", Dark, tab1);
ESPUI.setVertical(vertswitcher); 

This must be done before ESPUI.begin() is called. Vertical layouts are currently only supported for sliders and switchers, and it is a purely visual change. Behaviour is identical. Mixing horizontal and vertical controls can result in some unpredictable layouts.

When you add multiple buttons to a single panel, the buttons have a title so they can be differentiated. For sliders and switchers this is not the case. Therefore you might want to add additional labels so that the controls can be distinguished. There is not yet automatic support for doing this, so the approach is to add labels that have been styled using inline styles. By doing this you can acheieve effects such as this:

Labelling grouped controls

The code to do this is in the completeExample example.

Wide controls

Controls can be set to be displayed "wide" with the function:

ESPUI.setPanelWide(controlid, true);

Important! This function should be called before ESPUI.begin or results will be unreliable.

Setting a control to wide tells ESPUI to lay out that control as if there was only a single column, even on wide displays. This can be applied to every element to force a single column layout, or to individual elements to customise the display.

Wide controls

Note that this will have no effect on small screens.

Graph (Experimental)

graph

The graph widget can display graph points with timestamp at wich they arrive

Use ESPUI.addGraphPoint(graphId, random(1, 50)); to add a new value at the current time, use ESPUI.clearGraph(graphId) to clear the entire graph. Graph points are saved in the browser in localstorage to be persistant, clear local storageto remove the points or use clearGraph() from a bbutton callback to provide a clear button.

There are many issues with the graph component currently and work is ongoing. Consider helping us out with development!

Captive Portal

ESPUI will redirect all unknown URLs it is asked for to the 'root' of the local HTTP server instead of responding with an HTTP code 404. This makes it act as a simple 'captive portal'. Note you must also set up the ESP to be a DNS server that responds to all DNS requests with the IP address of the ESP. This only effective when the ESP is acting as a WiFi hotspot in AP mode and assigning itself as the DNS server to connected clients.

All the example sketches include the DNS related code and will work as captive portals when used as a hotspot. In the event you wish to disable this feature you can do so by removing the DNS server code and adding the code below.

ESPUI.captivePortal = false;

Notes for Development

If you want to work on the HTML/CSS/JS files, do make changes in the data directory. When you need to transfer that code to the ESP, run tools/prepare_static_ui_sources.py -a (this script needs python3 with the modules htmlmin, jsmin and csscompressor). This will generate a) minified files next to the original files and b) the C header files in src that contain the minified and gzipped HTML/CSS/JS data. Alternatively, you can specify the --source and --target arguments to the prepare_static_ui_sources.py script (run the script without arguments for help) if you want to use different locations.

If you don't have a python environment, you need to minify and gzip the HTML/CSS/JS files manually. I wrote a little useful jsfiddle for this, see here.

If you change something in HTML/CSS/JS and want to create a pull request, please do include the minified versions and corresponding C header files in your commits. (Do NOT commit all the minified versions for the non changed files)

Experimental debugging environment using emulation on host

It is possible to run or debug this library on a unix-like computer (Linux, macOS, WSL) without flashing on hardware, and with your favourite debugging tools (gdb, valgrind, ...). This is accomplished through the esp8266/Arduino "emulation on host" environment.

A fake AsyncWebserver library is needed because lwIP is not yet ported to the emulation environment. Full instructions can be found in this project's readme page.

Changelog for 2.1:

  • Adds the ability to have inline styles for widgets and panels
  • Adds LittleFS on the ESP32
  • Cleans up examples
  • Adds Button Animation
  • Adds chunking for the widgets so you can add even more of them
  • Fixes lots of bugs related to invisible UI elements and sliders
  • Adds the ability to change port

Changelog for 2.0:

  • ArduinoJSON 6.10.0 Support
  • Split pad into pad and padWithCenter
  • Cleaned order of parameters on switch and pad
  • Changes all numbers to actually be numbers (slider value, number value, min and max)

Contribute

Liked this Library? You can support me by sending me a ☕ Coffee.

Otherwise I really welcome Pull Requests.

espui's People

Contributors

a-damw avatar bastiengrignon avatar chrschu90 avatar croghostrider avatar d-a-v avatar don41382 avatar enwi avatar ericbcreator avatar eringerli avatar flawededge avatar gschintgen avatar iangray001 avatar leokeba avatar marcusmiess avatar martinmueller2003 avatar ncmreynolds avatar noctr avatar orithena avatar pcbbc avatar per1234 avatar roboticafacil avatar rteliuk avatar s00500 avatar sunlord2k avatar ta1aub avatar tecteun avatar wvdv2002 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

espui's Issues

Empty Controls

Hi ,
I installed dependencies , libraries - prepared FS
But when connect to ESP I have blank page with Control Offline and no buttons/sliders etc....
Where Should I search the problem. It basically display only content from the Index.html without anything specified in gui.ino

Password protection

Is your feature request related to a problem? Please describe.
No problem. We're using a ESP with ESPUI at a hackerspace and would like to set a password 👍

Describe the solution you'd like
Just a basic auth where you can give username and password would be sufficient!

Describe alternatives you've considered
Well, alternative would be a full pw auth... but that's a little bit overkill - and you still want the lib to fit on all controllers ;)

More than 8 User interface Elements not possible??

GREAT LIB! BUT...
I can only see maximum eight User interface Elements/Controls in my browser the 9th 10th and so on can not be seen...even the original example behave same.
Is this limitation of the lib?

Screenshots
gui_scr_cap
r problem.

Desktop:
Windows 7 64bit
Firefox Quantum 63.0.3 (64-bit)
Chrome Version 71.0.3578.80 (Official Build) (64-bit)
and more others...same behavior.

error during compilation

I've installed the library and pre-req libraries. When I compile the example I get the following messages:

Arduino:1.8.5 (Windows 10), Scheda:"ESP32 Dev Module, QIO, 80MHz, 4MB (32Mb), 921600, None"

ATTENZIONE: la libreria FS dichiara di funzionare sulle architetture (esp32) e potrebbe non essere compatibile con la tua scheda che utilizza l'architettura (esp2)
ATTENZIONE: la libreria SPIFFS dichiara di funzionare sulle architetture (esp32) e potrebbe non essere compatibile con la tua scheda che utilizza l'architettura (esp2)
ATTENZIONE: la libreria WiFi dichiara di funzionare sulle architetture (esp32) e potrebbe non essere compatibile con la tua scheda che utilizza l'architettura (esp2)
C:\Users\roberto\Documents\arduino librerie\libraries\ESPUI\src\ESPUI.cpp: In function 'void onWsEvent(AsyncWebSocket*, AsyncWebSocketClient*, AwsEventType, void*, uint8_t*, size_t)':

C:\Users\roberto\Documents\arduino librerie\libraries\ESPUI\src\ESPUI.cpp:177:10: error: enumeration value 'WS_EVT_PONG' not handled in switch [-Werror=switch]

switch (type) {

      ^

C:\Users\roberto\Documents\arduino librerie\libraries\ESPUI\src\ESPUI.cpp:177:10: error: enumeration value 'WS_EVT_ERROR' not handled in switch [-Werror=switch]

cc1plus.exe: some warnings being treated as errors

exit status 1
Errore durante la compilazione per la scheda ESP32 Dev Module.

Questo report potrebbe essere più ricco di informazioni abilitando l'opzione
"Mostra un output dettagliato durante la compilazione"
in "File -> Impostazioni"
+++++++++++++++++++++++
any suggestion? thanks

Is it possible to dynamically remove controls?

Is it possible to dynamically remove controls?
For example, remove some items in Select?

We can remove controls form the controls list. Like that:
But how to send a request to update the page?

bool ESPUIClass::remControl(uint16_t id)
{
  if(nullptr == this->controls) return false;

  Control * it = this->controls;
  
  if(id == it->id) {
    this->controls = it->next;
    delete it;
    //need something for update the page
    return true;
  }

  Control * it_next = it->next;
  while(nullptr != it_next && id != it_next->id) {
    it = it_next;
    it_next = it_next->next;
  }

  if(nullptr != it_next) {
    it->next = it_next->next;
    delete it_next;
    //need something for update the page
    return true;
  }
  
  return false;
}

Support line breaks

How difficult would it be to add a "control" item that acts as a standard line break? I'm trying to build an app that has various controls on a page that I want stacked vertically for some controls, while others would use the standard flow layout.

Thanks!

List box or popup menu list

Is your feature request related to a problem? Please describe.
Hello it would be great to have a listbox or pop menu to chose for example from a city list (i.e. for weather station) or other parameters to be configured

ArduinoJson Migration from 5 to 6 / Version conflicts using other Frameworks

Is there a plan to migrate the espui framework to ArduinoJson Version 6? I have conflicts using other Frameworks which require already Version 6.

An update from the sources of ESPUI to ArduinoJson v6 will be perfect.

Here you can find the migration documentation:
*ttps://arduinojson.org/v6/doc/upgrade/

Update Arduino library version to V1.5

Hi S00500,
Thanks for the great library, it works as it should. Can't wait to test the V1.5 version.

Could you maybe update the version in the library.properties file to V1.5 so the new version automatically shows up in the Arduino library manager?
Thanks!

Reconnect on error: dhcps: send_offer>>udp_sendto result 0

Firstly, thank you for this excellent effort at making a library that is useful and so competently implemented. I couldn't decide whether this was an issue or a feature as it seems to be a bit of both.

I have only tried using the GUI sample code on an ESP32, with the main loop() function

void loop(void) {
  dnsServer.processNextRequest();

  if (millis() - oldTime > 5000) {
    ESPUI.print("Millis:", String(millis()));
    switchi = !switchi;
    ESPUI.updateSwitcher("Switch one", switchi);
    oldTime = millis();
  }
}

If you leave the ESP32 running, eventually this appears on the serial monitor:

dhcps: send_offer>>udp_sendto result 0
Disconnected!

I traced this to the event handler for the sockets code in ESPUI.cpp

void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
               AwsEventType type, void *arg, uint8_t *data, size_t len)

After this, the web server is non responsive and there is no way to restart things without resetting the ESP32. Ideally I'd expect to have a IsConnected method on the dnsServer object and then reconnect if it is not connected.

Perhaps you have already got this feature as a work in progress. Otherwise I think this would be a useful and possibly necessary feature for a device that is going to be always on and accessed via a browser from a PC or mobile device.

Thank you.

A lot of data to transmit causes Soft WDT Reset

I have several controls in my program. If the webpage is loaded, the configuration is sent to the client. Seems to be a lot of data. Transmitting obviously takes too long so the watchdog resets the ESP. Do you have an idea how to prevent the watchdog reset? Calling yield() on the right place could be an idea, but for that transmitting the page source should be split up.

Please find a code snipped below, just to get an idea how much data should be sent to the client.

  uint16_t dashboardTab = ESPUI.addControl(ControlType::Tab, "Dashboard", "Dashboard", ControlColor::None);
  uint16_t inputTab = ESPUI.addControl(ControlType::Tab, "Eingänge", "Eingänge", ControlColor::None);
  uint16_t outputTab = ESPUI.addControl(ControlType::Tab, "Ausgänge", "Ausgänge", ControlColor::None);
  uint16_t settingsTab = ESPUI.addControl(ControlType::Tab, "Einstellungen", "Einstellungen", ControlColor::None);

  uint8_t countSensors = sensors.getDS18Count();
  if (countSensors > 0)
  {
    uint16_t sensorTab = ESPUI.addControl(ControlType::Tab, "Temperaturen", "Temperaturen", ControlColor::None);

    sensor[0].displayControlId = ESPUI.addControl(ControlType::Label, "Temperatur 1", "kein Wert", ControlColor::None, sensorTab);
    sensor[0].nameControlId = ESPUI.addControl(ControlType::Text, "Sensor 1", "Name Sensor 1", ControlColor::None, sensorTab, &sensor1Callback);
    if (countSensors > 1)
    {
      sensor[1].displayControlId = ESPUI.addControl(ControlType::Label, "Temperatur 2", "kein Wert", ControlColor::None, sensorTab);
      sensor[1].nameControlId = ESPUI.addControl(ControlType::Text, "Sensor 2", "Name Sensor 2", ControlColor::None, sensorTab, &sensor2Callback);
      if (countSensors > 2)
      {
        sensor[2].displayControlId = ESPUI.addControl(ControlType::Label, "Temperatur 3", "kein Wert", ControlColor::None, sensorTab);
        sensor[2].nameControlId = ESPUI.addControl(ControlType::Text, "Sensor 3", "Name Sensor 3", ControlColor::None, sensorTab, &sensor3Callback);
      }
    }
  }

  input[0].displayControlId = ESPUI.addControl(ControlType::Label, "Input 1", "Inaktiv", ControlColor::None, dashboardTab);
  input[0].nameControlId = ESPUI.addControl(ControlType::Text, "Input 1 Name", "Input", ControlColor::None, inputTab, &input1Callback);
  input[0].emailBodyControlId = ESPUI.addControl(ControlType::Text, "Input 1 Email Body", "Eingang 1 aktiv", ControlColor::None, inputTab, &input1Callback);

  input[1].displayControlId = ESPUI.addControl(ControlType::Label, "Input 2", "Inaktiv", ControlColor::None, dashboardTab);
  input[1].nameControlId = ESPUI.addControl(ControlType::Text, "Input 2 Name", "Input", ControlColor::None, inputTab, &input2Callback);
  input[1].emailBodyControlId = ESPUI.addControl(ControlType::Text, "Input 2 Email Body", "Eingang 2 aktiv", ControlColor::None, inputTab, &input2Callback);

  input[2].displayControlId = ESPUI.addControl(ControlType::Label, "Input 3", "Inaktiv", ControlColor::None, dashboardTab);
  input[2].nameControlId = ESPUI.addControl(ControlType::Text, "Input 3 Name", "Input", ControlColor::None, inputTab, &input3Callback);
  input[2].emailBodyControlId = ESPUI.addControl(ControlType::Text, "Input 3 Email Body", "Eingang 3 aktiv", ControlColor::None, inputTab, &input3Callback);

  input[3].displayControlId = ESPUI.addControl(ControlType::Label, "Input 4", "Inaktiv", ControlColor::None, dashboardTab);
  input[3].nameControlId = ESPUI.addControl(ControlType::Text, "Input 4 Name", "Input", ControlColor::None, inputTab, &input4Callback);
  input[3].emailBodyControlId = ESPUI.addControl(ControlType::Text, "Input 4 Email Body", "Eingang 4 aktiv", ControlColor::None, inputTab, &input4Callback);

  output[0].displayControlId = ESPUI.addControl(ControlType::Switcher, "Output 1", "0", ControlColor::None, dashboardTab, &output1SwitchCallback);
  output[0].nameControlId = ESPUI.addControl(ControlType::Text, "Output Name", "Output", ControlColor::None, outputTab, &output1Callback);

  output[1].displayControlId = ESPUI.addControl(ControlType::Switcher, "Output 2", "0", ControlColor::None, dashboardTab, &output2SwitchCallback);
  output[1].nameControlId = ESPUI.addControl(ControlType::Text, "Output Name", "Output", ControlColor::None, outputTab, &output2Callback);

  smtpSettings.serverControlId = ESPUI.addControl(ControlType::Text, "SMTP Server", "", ControlColor::None, settingsTab, &smtpSettingsCallback);
  smtpSettings.userControlId = ESPUI.addControl(ControlType::Text, "SMTP Benutzer", "", ControlColor::None, settingsTab, &smtpSettingsCallback);
  smtpSettings.passwordControlId = ESPUI.addControl(ControlType::Text, "SMTP Passwort", "", ControlColor::None, settingsTab, &smtpSettingsCallback);

  noIpSettings.serverControlId = ESPUI.addControl(ControlType::Text, "NoIP Domain", "", ControlColor::None, settingsTab, &noIpSettingsCallback);
  noIpSettings.userControlId = ESPUI.addControl(ControlType::Text, "NoIP Benutzer", "", ControlColor::None, settingsTab, &noIpSettingsCallback);
  noIpSettings.passwordControlId = ESPUI.addControl(ControlType::Text, "NoIP Passwort", "", ControlColor::None, settingsTab, &noIpSettingsCallback);

That's the output:

{"type":200,"sliderContinuous":false,"controls":[{"type":0,"label":"IoT-Alarm"},{"id":"0","type":11,"label":"Dashboard","value":"Dashboard","color":255},{"id":"1","type":11,"label":"Eingänge","value":"Eingänge","color":255},{"id":"2","type":11,"label":"Ausgänge","value":"Ausgänge","color":255},{"id":"3","type":11,"label":"Einstellungen","value":"Einstellungen","color":255},{"id":"4","type":11,"label":"Temperaturen","value":"Temperaturen","color":255},{"id":"5","type":4,"label":"Temperatur 1","value":"26.1","color":255,"parentControl":"4"},{"id":"6","type":8,"label":"Sensor 1","value":"Name Sensor 1","color":255,"parentControl":"4"},{"id":"7","type":4,"label":"Temperatur 2","value":"25.9","color":255,"parentControl":"4"},{"id":"8","type":8,"label":"Sensor 2","value":"Name Sensor 2","color":255,"parentControl":"4"},{"id":"9","type":4,"label":"Input 1","value":"Inaktiv","color":255,"parentControl":"0"},{"id":"10","type":8,"label":"Input 1 Name","value":"Input","color":255,"parentControl":"1"},{"id":"11","type":8,"label":"Input 1 Email Body","value":"Eingang 1 aktiv","color":255,"parentControl":"1"},{"id":"12","type":4,"label":"Input 2","value":"Inaktiv","color":255,"parentControl":"0"},{"id":"13","type":8,"label":"Input 2 Name","value":"Input","color":255,"parentControl":"1"},{"id":"14","type":8,"label":"Input 2 Email Body","value":"Eingang 2 aktiv","color":255,"parentControl":"1"},{"id":"15","type":4,"label":"Input 3","value":"Inaktiv","color":255,"parentControl":"0"},{"id":"16","type":8,"label":"Input 3 Name","value":"Input","color":255,"parentControl":"1"},{"id":"17","type":8,"label":"Input 3 Email Body","value":"Eingang 3 aktiv","color":255,"parentControl":"1"},{"id":"18","type":4,"label":"Input 4","value":"Inaktiv","color":255,"parentControl":"0"},{"id":"19","type":8,"label":"Input 4 Name","value":"Input","color":255,"parentControl":"1"},{"id":"20","type":8,"label":"Input 4 Email Body","value":"Eingang 4 aktiv","color":255,"parentControl":"1"},{"id":"21","type":5,"label":"Output 1","value":"0","color":255,"p
Soft WDT reset

>>>stack>>>

ctx: sys
sp: 3fffeac0 end: 3fffffb0 offset: 01b0

Any help is appreciated.

Markus

[1.8.9] Multiple libraries were found for "WiFiUdp.h"

I cannot get the gui example sketch to compile for Feather HUZZAH board.
The compiler fails with the following error message:

C:\Users\simon\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\libraries\ArduinoOTA\ArduinoOTA.cpp: In member function 'void ArduinoOTAClass::_runUpdate()':

C:\Users\simon\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\libraries\ArduinoOTA\ArduinoOTA.cpp:281:3: error: 'stopAll' is not a member of 'WiFiUDP'

   WiFiUDP::stopAll();

   ^

Multiple libraries were found for "WiFiUdp.h"
 Used: C:\Program Files (x86)\Arduino\libraries\WiFi
 Not used: C:\Users\simon\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi
exit status 1
Error compiling for board Adafruit Feather HUZZAH ESP8266.

I tried to include the correct WiFiUdp.h using a hardcoded absolute path. But this fails at the next include instance include/slist.h

Additional Info

  • Fresh install of Arduino 1.8.9 (also deleted the AppData/Arduino15 folder)

Installed Libraries

  • Adafruit_NeoPixel
  • ArduinoJson (5.x)
  • ESPAsyncTCP
  • ESPAsyncWebServer
  • ESPUI
  • ESP_Async_E1.31

error during compilation

Hi
I have recently used this library on windows 10 and Iwas quite happy with it
But i had to move my whole work to linux(parrot OS) and after installing arduino 1.8.7 and esp32 package, I started with gui example. It didn't work. Here's the error message:
Arduino: 1.8.7 (Linux), Board: "ESP32 Dev Module, Disabled, Default, QIO, 80MHz, 4MB (32Mb), 921600, None"

Build options changed, rebuilding all
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:27: error: field 'call' has incomplete type 'tcpip_api_call'
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: forward declaration of 'struct tcpip_api_call'
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_output(tcp_pcb*)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:291:65: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:291:65: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_write(tcp_pcb*, const char*, size_t, uint8_t)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:307:64: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_write_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:307:64: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_recved(tcp_pcb*, size_t)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:322:65: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:322:65: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_connect(tcp_pcb*, ip_addr_t*, uint16_t, tcp_connected_fn)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:338:66: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:338:66: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_close(tcp_pcb*)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:352:64: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:352:64: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_abort(tcp_pcb*)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:367:64: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:367:64: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'esp_err_t _tcp_bind(tcp_pcb*, ip_addr_t*, uint16_t)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:382:63: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:382:63: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: In function 'tcp_pcb* _tcp_listen_with_backlog(tcp_pcb*, uint8_t)':
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:397:65: error: invalid conversion from 'err_t ()(tcpip_api_call) {aka signed char ()(tcpip_api_call)}' to 'tcpip_api_call_fn {aka signed char ()(tcpip_api_call_data)}' [-fpermissive]
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call*)&msg);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:397:65: error: cannot convert 'tcpip_api_call*' to 'tcpip_api_call_data*' for argument '2' to 'err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call_data*)'
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:259:12: note: class type 'tcpip_api_call' is incomplete
struct tcpip_api_call call;
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp: At global scope:
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:624:6: error: prototype for 'void AsyncClient::_dns_found(ip_addr_t*)' does not match any in class 'AsyncClient'
void AsyncClient::_dns_found(ip_addr_t ipaddr){
^
In file included from /root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:24:0:
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.h:84:10: error: candidate is: void AsyncClient::_dns_found(_ip_addr
)
void _dns_found(struct _ip_addr ipaddr);
^
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:946:6: error: prototype for 'void AsyncClient::_s_dns_found(const char
, ip_addr_t*, void*)' does not match any in class 'AsyncClient'
void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){
^
In file included from /root/Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp:24:0:
/root/Arduino/libraries/AsyncTCP/src/AsyncTCP.h:164:17: error: candidate is: static void AsyncClient::_s_dns_found(const char*, _ip_addr*, void*)
static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg);
^
Multiple libraries were found for "WiFi.h"
Used: /root/Arduino/hardware/espressif/esp32/libraries/WiFi
Not used: /home/user/arduino-1.8.7/libraries/WiFi
exit status 1
Error compiling for board ESP32 Dev Module.

Using ESPUI with custom AsyncWebserver Setup

I'd like to use the ESPUI along with the AsyncWebserver serving html and using the great SpiffsEditor which makes changes so much faster.
Latest in server.begin() vs ESPUI.beginSPIFFS() in the sketch shows the problem. Any suggestion ? In the end espui lib configures the webserver and a sketch does the same. It maybe helps #16 and #17 as well. Thanks, Thorsten

My awesome library

Hello, back when I didn't know about this project, I would start developing my own GUI for ESP.

Since I found out that it's still a bit different from yours, I continued the development. I believe it to be THE most feature-rich GUI library for ESP, since it already supports list boxes, text boxes, textareas, optional synchronization between clients, advanced methods of layout control and more.

I still am working on it, but I will be releasing it soon under the MIT licence. Right now the examples work fine and it's more or less stable and working. Feel free to check it out and/or use any code from it!

https://github.com/thegoodhen/TGH-GUI

Graph support

I just discover your incredible library! It was something was well needed. The thing that surprise me the most is that you make it easy to use. This definitely will empower kids and hobbyist alike to be more creative with their projects. One enchantment i can think of is the the support for graphs. It make tremendous sense since most hobby projects is about collect and visualize data. Whether station, garden monitor, temperature monitor, air quality sensor and the list going on. The fact that everything can be self contain with out a external server make it ideal for spread adoption.

request,add such as led_control_button.fan.motor...so or

your project is good idea.to view and control esp. but if request,
1 i think it can add some such as led_control_button.fan_button.motor_button.led_color_lable.... so or.
2 in html files system .add a setting web page to setting (add.delete.change.rename.location.relate control_pin)the buttons or lables.
thank you.

[2.0] More than 31 elements do not work

Describe the bug
If defining more than 31 controls (reasonable with a few tabs, especially if you use min/max/step for numeric controls and pulldowns), the 32 control is rendered without color and parent. (At least in my setup https://github.com/doppelgrau/esp32-aog/tree/Cleanup - with shorter titel maybe it would happen later).

To Reproduce
Create GUI with lots of controls and find items missing.
Use the web dev inspection of your browser and see that in the first websocket message not all controls are transmitted.

Expected behavior
all controls are transmitted.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Problem seems somehow related to the serialization of the controls, increasing DynamicJsonDocument document(4000) from 4000 to 8000 in ESPUIClass::jsonDom(AsyncWebSocketClient *client) did "solve" the problem.
Since I'm planing to add more controls (especially some pulldowns with more entries), I'm not sure if that's the way to go.

Joined existing network, webpage timeouts

If I create a custom AP with the unmodified example sketch, I can access all the controls with the provided example. Beautiful.
If I change the setup() commenting out the AP code and uncommenting the join existing network code it connects to the network, displays the assigned IP, shows "UI Initialized" but the webpage at this address timeouts, using my mobile phone or chrome on the desktop.
Tried with and without HTTP BasicAuth, same results.

[edit] forgot to add, ESP8266 on Arduino 1.89 IDE

Multiple web pages

This is an excellent library. Thank you for all the wonderful features.

I created a webpage using the library and it works good. However I am not sure how to create multiple pages. Example, one page where I can have all the buttons etc to control the devices and additional page for configuration.
Could you kindly guide on how to create multiple pages.

Sending float number

Sending float number.
By creating a small program for a wifi thermostat, I found a small obstacle in sending float values.

Describe the solution you'd like
I propose a possible solution which consists of adding a class for float values:

uint16_t ESPUIClass::floatnumber(const char *label, void (*callback)(Control *, int), ControlColor color, float number, float min, float max) {
uint16_t numberId = addControl(ControlType::Number, label, atof(number), color, Control::noParent, callback);
addControl(ControlType::Min, label, atof(min), ControlColor::None, numberId);
addControl(ControlType::Max, label, atof(max), ControlColor::None, numberId);
return numberId;
}

It will not be an elegant solution .... but it could serve the purpose.

FW Upload Widget

Is your feature request related to a problem? Please describe.
For projects that use your Lib it would be cool if its possible to update the Firmware over the webpage. So it possible to update the FW without having to compile. Makes distributing new FW a lot easyer and usable by non Programmers.

Describe the solution you'd like
Make a new Widget with button that opens a file explorer to select a file to upload.

Describe alternatives you've considered
Programming it and Making a Pull request. But since i dont know with the new changes comming in/ API changes when to start with this. And I cant do the WEB part thats why im starting with your library.
Or Asking you to create a callback where we can configure the Webserver or make the webserver Public.
So that it possible to add more stuff/pages to the webserver without having to write stuff into the library.

Additional context
My Led project TinyPixelMapper need a basic web UI and thats why im looking into your Library.

This library is difficult to find

I couldn't find this library while looking for something that would provide a user interface over websockets. Not sure if some tags or other type of search engine optimization would help, but letting you know as a feedback.

This library is so well hidden from the search engines I have actually started working on my own library because I thought nothing like this exists. Will soon release alpha. Oh well. ;-;

Black color for UIs

Describe the bug
COLOR_NONE has the same definition value as COLOR_ALIZARIN.

To Reproduce
Steps to reproduce the behavior:
If you create an UI with COLOR_NONE or COLOR_ALIZARIN has the same behaviour.

Expected behavior
I expected to be a 'black' or dark color, which should be the default color for a white background.

ESPUI as Class Member?

Hello guys!
Thank you for this very nice project!
I have an issue putting the ESPUI-Library into my existing project, which works within its own Library.
I have something like this:

class Myclass{
  void setupUI(); //setup ESPUI...
  void doStuff( Control* sender, int value ); //do something
}

void Myclass::setupUI(){
  /*** add a select object to UI ***/
  uint16_t select = ESPUI.addControl( ControlType::Select, "Select:", "", ControlColor::Alizarin, tab1, &doStuff ); //<-- this causes an Error
  ESPUI.addControl( ControlType::Option, "Option1", "Opt1", ControlColor::Alizarin, selectMode );
  ESPUI.addControl( ControlType::Option, "Option2", "Opt2", ControlColor::Alizarin, selectMode );
  ESPUI.addControl( ControlType::Option, "Option3", "Opt3", ControlColor::Alizarin, selectMode );

  ESPUI.begin("ESPUI Control");
}

void Myclass::doStuff( Control* sender, int value ){
  
}

It causes an compiling Error like:

error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.

Is it even possible to work with ESPUI withing an existing class? I don't understand why I can put a function as pointer to the addControl-method in the .ino-file but not within my class?
Can anyone help me or has the same problem?

Thank you really much

option to rotate sliders

**Is your feature request related to a problem?
using the sliders to control features like direction / speed, or elevation / rotation it is not very intuitive if both sliders have the same orientation

Describe the solution you'd like
The ability to rotate the sliders either verticaly or horizontally. This would be very good for things like pan / tilt camera platforms or remote controlled car projects

sender.value can be stored in a variable?

Hi. i have a little problem !
I want to store sender.value text writen in TextCall, in to a variable, and after that, to print on a LCD cristal 20x4.
I don't know how to store sender.value in a variable (ex. string).
Can you help me?

ps. Sorry for my bad english, i'm not native

#define debug true messes with async wifimanager

A nice addition to ESPUI is the ASYNC wifimanager project . Sadly fresh out of the box ESPUI and the wifi manager don't compile together because of the way debugging is handled, the "#define debug true" statement in the code. Maybe change it into something better defined and with capitals #define DEBUG_ESPUI or something.

Enhancement: Only upload gzipped data to the ESP?

I'm wondering whether it is necessary to upload non-gzipped data to the ESP at all, since all browsers support Content-Encoding: gzip.

Doing so would save a lot of space in PROGMEM ... for example, the minified style.css is at 19.5KB, while its gzipped data is a 2.8KB byte array (when compiled). We could save *.min.<type>.gz files in the examples/gui/data directory (for the sketch data uploader tool) and move the original HTML/CSS/JS files somewhere else. Then we can lose the minified data from the *.h files and keep only the gzipped byte array.

Since I know it's rather easy (for me, at least ^^) to modify the prepare_static_ui_sources.py script to reflect such a directory structure, this would actually be viable. Some library code would need refactoring, too, I assume (I didn't look too deep into the source code).

Probably it would be best to serve original files if they do exist in SPIFFS (to ease the HTML/CSS/JS edit-deploy-run development cycle) and only serve gzipped versions if they're the only version.

Thoughts? Comments? Did I overlook something? Would this approach break old projects that decide to update the ESPUI library?

want to add a function to the module

Hello, your espui is a very good module.
I hope this module adds a function, a button is associated with a pin port, and the state of the pin port is fed back.
Feedback pin port has high or low level, or analog value, feedback to the web page, color change, or numerical display.
thks

Multiple buttons using the same container

Hi,

it would be nice to have lets say 6 buttons which are nested inside the same container. The container could have a title like: "Dimming" and there would be 6 buttons with different dimming levels.

It would look cleaner than having 6 individual buttons which all have the title "Dimming".

Thanks!

Switchable Slider Behaviour in 2.0

PlatformIO all boards/libraries updated to latest (except ArduinoJson == 5.13.4)
ESP32 DOIT DEV KIT V1

Using example code the web server crashes after continually moving one of the sliders for ~5-20 seconds. This only occurs when connecting to an existing wifi network. The web server does not appear to ever crash when running example code configured as a wifi access point (ie: when running example exactly as posted).

Placing print statements in the 5 second 'flip switch' routine shows the code is still running .. only the web interface is down. As a test I found that if I force a restart of the WiFI session every minute the web server comes back online if it was hung prior to the wifi restart.

WiFi.disconnect();
WiFi.begin(ssid, password);

This occurs when connecting with chrome and firefox browsers on both mac and iOS.

ESP32 crashing with more than 27 controls

Hi Lukas, as in the title, having up to 27 controls is no problem but when I add another one, the ESP32 crashes every time when I try to open the user interface webpage.
Maybe the limit of 32 in WS_MAX_QUEUED_MESSAGES is set too high? Or could there be another issue?

This is the error message:

Connected: 1
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400014e8  PS      : 0x00060b30  A0      : 0x800e3fa9  A1      : 0x3ffcbda0  
A2      : 0x00000006  A3      : 0x00000004  A4      : 0x000000ff  A5      : 0x0000ff00  
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x800d87f8  A9      : 0x3ffcbd70  
A10     : 0x3ffcfce8  A11     : 0x00000010  A12     : 0x3ffcf6e8  A13     : 0x00000604  
A14     : 0x00000fa0  A15     : 0xff000000  SAR     : 0x00000010  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000004  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  

Backtrace: 0x400014e8:0x3ffcbda0 0x400e3fa6:0x3ffcbdb0 0x400dae8a:0x3ffcbdd0 0x400db04e:0x3ffcbe60 0x401544db:0x3ffcc1c0 0x4015486a:0x3ffcc1e0 0x400ddb8b:0x3ffcc230 0x400ddc01:0x3ffcc270 0x40154916:0x3ffcc290 0x400df739:0x3ffcc2b0 0x400dc761:0x3ffcc2d0 0x400dc885:0x3ffcc300 0x400dce69:0x3ffcc320 0x4008ba0d:0x3ffcc350

Rebooting...

On a side note: I increased WS_MAX_QUEUED_MESSAGES to 32 for an ESP8266 and it works fine but also up to 27 controls.

BTW: excellent work on this library, it is great for my alarm clock project (and many to come)!

Eric

Text input support

Are you working on a text input? I would be in need of that right now. How could i go about this myself to create it, if possible?

json issue while compiling

Hi,

i do think that i have some issue with related to json's.

I already found all the missing libraries where your code referred to, but this is now my next problem to get it compiled.

THanks your help in advance!

BR
Jussi

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp: In member function 'void ESPUIClass::print(int, String)':

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:423:5: error: 'StaticJsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

 ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:423:5: note: suggested alternative:

In file included from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/StaticJsonDocument.hpp:8:0,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:10,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.h:7,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:1:

C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/StaticJsonBuffer.hpp:110:7: note: 'ArduinoJson::Internals::StaticJsonBuffer'

class StaticJsonBuffer : public Internals::StaticJsonBufferBase {

   ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:423:27: error: 'jsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

                       ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:428:10: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

 root.printTo(json);

      ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp: In member function 'void ESPUIClass::updateSlider(int, int, int)':

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:450:5: error: 'StaticJsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

 ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:450:5: note: suggested alternative:

In file included from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/StaticJsonDocument.hpp:8:0,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:10,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.h:7,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:1:

C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/StaticJsonBuffer.hpp:110:7: note: 'ArduinoJson::Internals::StaticJsonBuffer'

class StaticJsonBuffer : public Internals::StaticJsonBufferBase {

   ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:450:27: error: 'jsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

                       ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:455:10: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

 root.printTo(json);

      ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp: In member function 'void ESPUIClass::updateSwitcher(int, bool, int)':

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:467:5: error: 'StaticJsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

 ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:467:5: note: suggested alternative:

In file included from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/StaticJsonDocument.hpp:8:0,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:10,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.h:7,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:1:

C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/StaticJsonBuffer.hpp:110:7: note: 'ArduinoJson::Internals::StaticJsonBuffer'

class StaticJsonBuffer : public Internals::StaticJsonBufferBase {

   ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:467:27: error: 'jsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

                       ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:472:10: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

 root.printTo(json);

      ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp: In member function 'void ESPUIClass::updateNumber(int, int, int)':

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:492:5: error: 'StaticJsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

 ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:492:5: note: suggested alternative:

In file included from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/StaticJsonDocument.hpp:8:0,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:10,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.h:7,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:1:

C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/StaticJsonBuffer.hpp:110:7: note: 'ArduinoJson::Internals::StaticJsonBuffer'

class StaticJsonBuffer : public Internals::StaticJsonBufferBase {

   ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:492:27: error: 'jsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

                       ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:497:10: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

 root.printTo(json);

      ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp: In member function 'void ESPUIClass::jsonDom(AsyncWebSocketClient*)':

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:547:5: error: 'StaticJsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

 ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:547:5: note: suggested alternative:

In file included from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/StaticJsonDocument.hpp:8:0,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:10,

             from C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.h:7,

             from C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:1:

C:\Users\NNN\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Memory/StaticJsonBuffer.hpp:110:7: note: 'ArduinoJson::Internals::StaticJsonBuffer'

class StaticJsonBuffer : public Internals::StaticJsonBufferBase {

   ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:547:27: error: 'jsonBuffer' was not declared in this scope

 StaticJsonBuffer<200> jsonBuffer;

                       ^

C:\Users\NNN\Documents\Arduino\libraries\ESPUI\src\ESPUI.cpp:559:10: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

 root.printTo(json);

      ^

exit status 1
Error compiling for board ESP32 Dev Module.

Captive portal

Is it possible to add a captive portal to the ESPUI interface?

Errors by compiling the Example fore ESP32 under ArduinoIDE1.8.5

After changing the following lines in src/ESPUI.cpp evrything compile fine and the Example runs
This is the first time iam playing with your library and Iam not lookting deeper in the COde for now, mybe ist not the optimal solution.

Here are the changes:

260c260
<     return;
---
>     return 0;
285c285
<     return;
---
>     return 0;
309c309
<     return;
---
>     return  0;
335c335
<     return;
---
>     return 0;
356c356
<     return;
---
>     return 0;

Problem with prepareFilesystem

Hi,

a JSON file is missing in the Library (ArduinoJson.h):

Arduino: 1.8.5 (Windows 7), Board: ""WeMos" WiFi&Bluetooth Battery, 80MHz, 921600"
In file included from C:\Users\ent42\Documents\Arduino\libraries\ESPUI\examples\prepareFilesystem\prepareFilesystem.ino:1:0:

C:\Users\ent42\Documents\Arduino\libraries\ESPUI\src/ESPUI.h:7:25: fatal error: ArduinoJson.h: No such file or directory

compilation terminated.

exit status 1
Fehler beim Kompilieren für das Board "WeMos" WiFi&Bluetooth Battery.

regular crash with "gui" example

Merry Christmas,
I experience regular crashes, on 8266 E12-F.
I rolled back to ESPUI packetmanager version 1.40 version of "GUI" example and initialised filesystem with prepareFS successfully.
After a short while I get crashes:

Exception (28):
epc1=0x4020acbc epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000c depc=0x00000000

ctx: cont
sp: 3fff08b0 end: 3fff0c80 offset: 01a0

stack>>>
3fff0a50: 3fff2c14 0000001d 00000001 40211634
3fff0a60: 00000020 00000000 3fff3724 4020ad3a
3fff0a70: 3fff2c14 0000001d 40209d84 402128d0
3fff0a80: 3ffef910 3ffef910 00000001 4020ad5e
3fff0a90: 3fff0b98 3ffef910 00000001 4020708e
3fff0aa0: 3fff0aa8 0000001d 3fff0ad0 00000001
3fff0ab0: 3ffef910 00000006 3fff0ad0 4020815c
3fff0ac0: 3ffe8a98 3fff0ad0 000000c8 0000003a
3fff0ad0: 3fff0ac0 3fff0ad8 3fff0ae8 3ffe88e8
3fff0ae0: 00000004 00000007 3fff0af8 3ffe88f0
3fff0af0: 00000004 00000001 00000000 3ffe88f8
3fff0b00: 00000002 3fff0b08 3fff0036 3ffe88f0
3fff0b10: 00000002 3fff0b18 31353932 40003231
3fff0b20: 00000000 3ffe88f8 00000002 3ffefb6c
3fff0b30: 00000010 3fff0bc0 00000000 4010053d
3fff0b40: 00000010 3fff0bd0 00000000 4010053d
3fff0b50: 00000003 11970471 00000000 00000000
3fff0b60: 00000010 3fff0bc0 3fff0bc0 40210d10
3fff0b70: 3ffe85bc 0000000a 3fff0bc0 40210d5f
3fff0b80: 3ffefb6c 000002ea 000002ea 4010020c
3fff0b90: 3fff0bf0 3ffef910 3fff2c14 0000001f
3fff0ba0: 0000001d 3fff2bec 0000001f 0000001d
3fff0bb0: 3ffefb6c 0000033a 00000006 402070e0
3fff0bc0: ffffffff 00000000 00000000 40210e54
3fff0bd0: 3fff0c4c 00000001 3ffef910 ffffffff
3fff0be0: 00000001 3fff0c40 3ffef910 4020826f
3fff0bf0: 3fff2e6c 0000000f 0000000a 40210d5f
3fff0c00: 3ffefb6c 000002ea 3fff0c40 40210d91
3fff0c10: 00000001 3ffef910 3fff0c40 40210de2
3fff0c20: 3ffe85bc 00000000 3fff0c50 3ffefc4c
3fff0c30: 3ffef904 3ffef910 3ffef900 40206eaf
3fff0c40: 3fff2e54 0000000f 0000000a 00000000
3fff0c50: 00000000 00000000 00000001 4021178d
3fff0c60: 3fffdad0 00000000 3ffefc45 402117b8
3fff0c70: feefeffe feefeffe 3ffefc60 40100718
<<<stack<<<

ets Jan 8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v3de0c112
~ld

IP address: 192.168.4.1
UI Initialized

Tried with 80mhz and 160mhz.
Regards //t

Time and color

Time and color input blocks will look very good in ESPUI.

Crash on page load

On a generic ESP32-dev board:

Uploaded the filesystem with the sketch. first time i didn't do a reset. I just let it run after upload. Not every file was written so i got the "Control Offline" message.
2nd upload and a reset after the upload fixed this.

But now when i load the page, i get nothing and the esp32 reboots. serial output below:


rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:812
load:0x40078000,len:0
load:0x40078000,len:11392
entry 0x40078a9c

IP address: 192.168.4.1
UI Initialized
CORRUPT HEAP: Bad tail at 0x3ffdf74a. Expected 0xbaad5678 got 0xbaad5600
assertion "head != NULL" failed: file "/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/./multi_heap_poisoning.c", line 199, function: multi_heap_free
abort() was called at PC 0x400dea73 on core 1

Backtrace: 0x40087ca8:0x3ffdd720 0x40087da7:0x3ffdd740 0x400dea73:0x3ffdd760 0x400879b9:0x3ffdd790 0x40083b76:0x3ffdd7b0 0x400840f9:0x3ffdd7d0 0x4000bec7:0x3ffdd7f0 0x400da09f:0x3ffdd810 0x400d8dda:0x3ffdd860 0x400d80d9:0x3ffdd8a0 0x400d6f08:0x3ffdd8e0 0x400d898b:0x3ffdd950 0x400d89f9:0x3ffdd990 0x400d8c0d:0x3ffdd9e0 0x400d4a66:0x3ffdda00 0x400d4c4d:0x3ffdda50

Rebooting...```

git commit -m "Changes to switch beginning line185 bcouse of enumeration values not explicitly handled in switch: [-Wswitch-enum]

Hi

I want to use Eclipse for Arduino and ESP programming (SLOEBER-IDE)
there is the default setting for the compiler [-Wswitch-enum]
Which gives Errors with your code:
I corrected this for me (for the beginning in a simple way), her are the changes:

@@ -183,10 +183,22 @@ void ESPUIClass::prepareFileSystem() {
 void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
                AwsEventType type, void *arg, uint8_t *data, size_t len) {
   switch (type) {
-  case WS_EVT_DISCONNECT:
+  case WS_EVT_DISCONNECT: {
     if (debug)
       Serial.printf("Disconnected!\n");
     break;
+  }
+  case WS_EVT_PONG: {
+    if (debug)
+      Serial.printf("WS_EVT_PONG!\n");
+    break;
+  }
+  case WS_EVT_ERROR: {
+    if (debug)
+      Serial.printf("WS_EVT_ERROR!\n");
+    break;
+  }
+  
   case WS_EVT_CONNECT: {
     if (debug) {
       Serial.print("Connected: ");
@@ -198,7 +210,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
       Serial.println("JSON Data Sent to Client!");
     }
   } break;
-  case WS_EVT_DATA:
+  case WS_EVT_DATA: {
     String msg = "";
     for (size_t i = 0; i < len; i++) {
       msg += (char)data[i];
@@ -249,6 +261,8 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
       c->callback(*c, SL_VALUE);
     }
     break;
+    }
+  default: break;
   }
 }

How to get const uint8_t VAR_GZIP array

Its working perfectly but i have searched alot but cant generate similar array when using gzip.
its giving me array with different values.

after

compression: (HEX format) 789ccd586d73e23610fe2baeae73d88303e1daf45ac0c910c235b4145220cd4ca73319618be089915c4986bb66f2dfbb925f30d8e4e0d29be9175eacd5b38ff6cdab9d47d4953ea386cb02c6bb0116c224d69358fbd25d98c41946cb19e1f0c87a72b12046f77e7a3bfefd76d49ff49a9cc88853041f7f47cc1704b51291de6fbd716770950a9025e138f0b2e59bdeb4371ef7ffe88d53899048c2b9bf223c13baeb4d3b939bebce609a0aad89c4225ce040664293dbe187c1e86e0324223a0fd83a87d3ed8cc7a30cc3c59cb3cdfecea0ff6767dc1fa6cb38f0ffc1dca799c07034ec353d32c751205321f4fc3c4fad2624e6d2b49ed6642698fbe850b236eec86c02bf8934d15a34eb75545dfbd463eb5ac05cac76d5164c488a97a48aea6b812c3bd95d639485843a29ba7284cba8600181bd0f0017cb194a0ab67d6ba237b03e9158460053c39e173b1069679e3c70522a27c947e0d665941257120f59cf39066ec004f93c052d5682cdc992adc8413476e97245650fd91eb88d1b7563c88c843790db264e94c85ee2e4ff44754984c00ffbad4cacd60a73c3757e998c86b51073414c52f3b0c496cd1cd3636eb42454d666ccfb642364b59274756bf25348924cbdeddf4ffbd3dea099894b5f06c4716b019e9140b35f629f5e13ec41be58b5855c0666b26ab5669ce0c7568a34e85c0292dac2d95a19248410f44cd4f6fc15c40298c6a9c8355355245a5261409e798674412be106aae68a8b5bd37fac2aaa9cb7176786ef391510a8f99e7aa27e690255d4ae2fce40024c79de1621a65a32c84453ad5adad09f276b8ec31863858388280cb5f3bc5d079ae768f75097b7d3e968f8995341601d7faab273c031669194503420005824089404ea54e2676ee0bb8f667a38db903c225625958cc27d72731c082558b462668178636603edf758d48250349f248bdc85ae63cd7c3c925ac8c90a8e7a15573fd3b2f314d47efb9b53ebf9790f2218f278bc86c2dbf1d2e4ae3fed5e43895729211cd48e3dae4e2c8ae110678201faa1027b600a9b3a5bfef42978c8a761240d952c4e458bced8c7d8886283c86857514b31e12d98d99d464100564fb4a4b66da153e43889e9dfbe350f24fb95496e7bbe24d0b762e72b843daa8a2a550ff4cabe64ecde74ae9a0ccc80530a5011e73e5f56b6f325c45e1c31ddde10da08db7829695e104e3367c1c9dca9bc890d1bba9b249a4c4737ed3a3e471945c5f02b94c03dc582e255ce1292b300a423b05fe09f8391ca8df26174a8457624cbcd31df98e3afe8ddd9e53b651070a4ff328b71ffe7ebe9813c0ab2e54cf8973119f43e1c4a6457b49c47f0653c2e3bdd5f0fe4b12b5ace63b69f471d820455990a2688a1edf44f3d7a6ce9df0a9bddda5f027a40f52f816c6c208357f2d4de2c102da21e4334879963ca5fc9344e8002d522ec3154f3a039aeb35772d5b159a05a443d866a0e33c7d47d25d3a4e017b816718fe1ba855a6c566eae3ad35eae57cec22d69ad756350b625eb71f21dc445f64ad7fa4eade6f68346a1531af4af00e30b5f51eacf89087cef3fe9d8d3c6a2a4ebe18fcb4c51fc75e2f9c285db3549ffefd79f6f8a38a60fa4622c7da8b4a7f08d3f3a95c629fcd2e68b49266d702529832ff54240c10fe5b9a277afa1279a8c5979933b84d56aff554f2451a92b6327c407b957374c53e94a212c3be16423a08a54142520e99421bd08eafbac896ee9238577893eb201174b1d9a709dcc0d21f27d34b15db8ff5da4774da18f36536fa326aa12abb9b31085faf1062b0b7500b2d96610948e7f740234d98e82d04d34b8bb1a4257ab70b74c0515bf0831df0b312f815055a38831db8b312bc150f5bc8811ecc5084a3074a12d82f0bd203c01c90f91d2b4d6ce536d3bd4800b1d35ca39355f98a899dc359075616e230a0c282ba2fd68a7a146b66616e956abb9bbd7a77b766f0f4736000d45cd7c594d1e27e42cdc2ca9526c354f0103ae479fd5f6124ec3b29e55a6c86ccee19cdae9a0c269d8d9f5de7967e72e91ce7776dcc83bdfdbc9a5c339b3f385dbf9c1de29cace7b3b2baece8ff6569e3b3fd910cca05ac523a85521051a755480ae385d40576e6c0ac2d9841476e4c7a1b0333ff854009b11a74689a799407933bb04c2f19cd279afa74689875bff020d6e1b71

Size: 1557

['x', '\x9c', '\xcd', 'X', 'm', 's', '\xe2', '6', '\x10', '\xfe', '+', '\xae', '\xae', 's', '\xd8', '\x83', '\x03', '\xe1', '\xda', '\xf4', 'Z', '\xc0', '\xc9', '\x10', '\xc2', '5', '\xb4', '\x14', 'R', ' ', '\xcd', 'L', '\xa7', '3', '\x19', 'a', '\x8b', '\xe0', '\x89', '\x91', '\', 'I', '\x86', '\xbb', 'f', '\xf2', '\xdf', '\xbb', '\x92', '', '0', '\xd8', '\xe4', '\xe0', '\xd2', '\x9b', '\xe9', '\x17', '^', '\xac', '\xd5', '\xb3', '\x8f', '\xf6', '\xcd', '\xab', '\x9d', 'G', '\xd4', '\x95', '>', '\xa3', '\x86', '\xcb', '\x02', '\xc6', '\xbb', '\x01', '\x16', '\xc2', '$', '\xd6', '\x93', 'X', '\xfb', '\xd2', ']', '\x98', '\xc4', '\x19', 'F', '\xcb', '\x19', '\xe1', '\xf0', '\xc8', 'z', 'r', '\xb1', ' ', 'F', '\xf7', '', 'z', ';', '\xfe', '\xfd', 'v', '\xd4', '\x9f', '\xf4', '\x9a', '\x9c', '\xc8', '\x88', 'S', '\x04', '\x1f', '\x7f', 'G', '\xcc', '\x17', '\x04', '\xb5', '\x12', '\x91', '\xde', 'o', '\xbd', 'q', 'g', 'p', '\x95', '\n', '\x90', '%', '\xe1', '8', '\xf0', '\xb2', '\xe5', '\x9b', '\xde', '\xb4', '7', '\x1e', '\xf7', '\xff', '\xe8', '\x8d', 'S', '\x89', '\x90', 'H', '\xc2', '\xb9', '\xbf', '"', '<', '\x13', '\xba', '\xeb', 'M', ';', '\x93', '\x9b', '\xeb', '\xce', '', '\x9a', '\n', '\xad', '\x89', '\xc4', '"', '\\', '\xe0', '@', 'f', 'B', '\x93', '\xdb', '\xe1', '\x87', '\xc1', '\xe8', 'n', '\x03', '$', '"', ':', '\x0f', '\xd8', ':', '\x87', '\xd3', '\xed', '\x8c', '\xc7', '\xa3', '\x0c', '\xc3', '\xc5', '\x9c', '\xb3', '\xcd', '\xfe', '\xce', '\xa0', '\xff', 'g', 'g', '\xdc', '\x1f', '\xa6', '\xcb', '8', '\xf0', '\xff', '\xc1', '\xdc', '\xa7', '\x99', '\xc0', 'p', '4', '\xec', '5', '=', '2', '\xc7', 'Q', ' ', 'S', '!', '\xf4', '\xfc', '<', 'O', '\xad', '&', '$', '\xe6', '\xd2', '\xb4', '\x9e', '\xd6', 'd', '&', '\x98', '\xfb', '\xe8', 'P', '\xb2', '6', '\xee', '\xc8', 'l', '\x02', '\xbf', '\x89', '4', '\xd1', 'Z', '4', '\xeb', 'u', 'T', ']', '\xfb', '\xd4', 'c', '\xeb', 'Z', '\xc0', '\\', '\xac', 'v', '\xd5', '\x16', 'L', 'H', '\x8a', '\x97', '\xa4', '\x8a', '\xea', 'k', '\x81', ',', ';', '\xd9', ']', 'c', '\x94', '\x85', '\x84', ':', ')', '\xba', 'r', '\x84', '\xcb', '\xa8', '', '\x01', '\x81', '\xbd', '\x0f', '\x00', '\x17', '\xcb', '\x19', 'J', '\n', '\xb6', '}', 'k', '\xa2', '7', '\xb0', '>', '\x91', 'X', 'F', '\x00', 'S', '\xc3', '\x9e', '\x17', ';', '\x10', 'i', 'g', '\x9e', '<', 'p', 'R', '*', "'", '\xc9', 'G', '\xe0', '\xd6', 'e', '\x94', '\x12', 'W', '\x12', '\x0f', 'Y', '\xcf', '9', '\x06', 'n', '\xc0', '\x04', '\xf9', '<', '\x05', '-', 'V', '\x82', '\xcd', '\xc9', '\x92', '\xad', '\xc8', 'A', '4', 'v', '\xe9', 'r', 'E', 'e', '\x0f', '\xd9', '\x1e', '\xb8', '\x8d', '\x1b', 'u', 'c', '\xc8', '\x8c', '\x84', '7', '\x90', '\xdb', '&', 'N', '\x94', '\xc8', '^', '\xe2', '\xe4', '\xff', 'D', 'u', 'I', '\x84', '\xc0', '\x0f', '\xfb', '\xad', 'L', '\xac', '\xd6', '\n', 's', '\xc3', 'u', '', '\x99', '\x8c', '\x86', '\xb5', '\x10', 's', 'A', 'L', 'R', '\xf3', '\xb0', '\xc4', '\x96', '\xcd', '\x1c', '\xd3', 'c', 'n', '\xb4', '$', 'T', '\xd6', 'f', '\xcc', '\xfb', 'd', '#', 'd', '\xb5', '\x92', 't', 'u', 'k', '\xf2', 'S', 'H', '\x92', 'L', '\xbd', '\xed', '\xdf', 'O', '\xfb', '\xd3', '\xde', '\xa0', '\x99', '\x89', 'K', '', '\x06', '\xc4', 'q', 'k', '\x01', '\x9e', '\x91', '@', '\xb3', '', 'b', '\x9f', '^', '\x13', '\xec', 'A', '\xbe', 'X', '\xb5', '\x85', '\', '\x06', 'f', '\xb2', 'j', '\xb5', 'f', '\x9c', '\xe0', '\xc7', 'V', '\x8a', '4', '\xe8', '\', '\x02', '\x92', '\xda', '\xc2', '\xd9', 'Z', '\x19', '$', '\x84', '\x10', '\xf4', 'L', '\xd4', '\xf6', '\xfc', '\x15', '\xc4', '\x02', '\x98', '\xc6', '\xa9', '\xc8', '5', 'S', 'U', '$', 'Z', 'R', 'a', '@', '\x9e', 'y', '\x86', 't', 'A', '+', '\xe1', '\x06', '\xaa', '\xe6', '\x8a', '\x8b', '[', '\xd3', '\x7f', '\xac', '', '\xaa', '\x9c', '\xb7', '\x17', 'g', '\x86', '\xef', '9', '\x15', '\x10', '\xa8', '\xf9', '\x9e', 'z', '\xa2', '~', 'i', '\x02', 'U', '\xd4', '\xae', '/', '\xce', '@', '\x02', 'L', 'y', '\xde', '\x16', '!', '\xa6', 'Z', '2', '\xc8', 'D', 'S', '\xad', 'Z', '\xda', '\xd0', '\x9f', "'", 'k', '\x8e', '\xc3', '\x18', 'c', '\x85', '\x83', '\x88', '(', '\x0c', '\xb5', '\xf3', '\xbc', ']', '\x07', '\x9a', '\xe7', 'h', '\xf7', 'P', '\x97', '\xb7', '\xd3', '\xe9', 'h', '\xf8', '\x99', 'S', 'A', '', '\x1d', '\x7f', '\xaa', '\xb2', 's', '\xc0', '1', 'f', '\x91', '\x94', 'P', '4', ' ', '\x00', 'X', '$', '\x08', '\x94', '\x04', '\xea', 'T', '\xe2', 'g', 'n', '\xe0', '\xbb', '\x8f', 'f', 'z', '8', '\xdb', '\x90', '<', '"', 'V', '%', '\x95', '\x8c', '\xc2', '}', 'r', 's', '\x1c', '\x08', '%', 'X', '\xb4', 'b', 'f', '\x81', 'x', 'c', 'f', '\x03', '\xed', '\xf7', 'X', '\xd4', '\x82', 'P', '4', '\x9f', '$', '\x8b', '\xdc', '\x85', '\xae', 'c', '\xcd', '|', '<', '\x92', 'Z', '\xc8', '\xc9', '\n', '\x8e', 'z', '\x15', 'W', '?', '\xd3', '\xb2', '\xf3', '\x14', '\xd4', '~', '\xfb', '\x9b', 'S', '\xeb', '\xf9', 'y', '\x0f', '"', '\x18', '\xf2', 'x', '\xbc', '\x86', '\xc2', '\xdb', '\xf1', '\xd2', '\xe4', '\xae', '?', '\xed', '^', 'C', '\x89', 'W', ')', '!', '\x1c', '\xd4', '\x8e', '=', '\xae', 'N', ',', '\x8a', '\xe1', '\x10', 'g', '\x82', '\x01', '\xfa', '\xa1', '\x02', '{', '', '\n', '\x9b', ':', '[', '\xfe', '\xf4', ')', 'x', '\xc8', '\xa7', 'a', '$', '\r', '\x95', ',', 'N', 'E', '\x8b', '\xce', '\xd8', '\xc7', '\xd8', '\x88', 'b', '\x83', '\xc8', 'h', 'W', 'Q', 'K', '1', '\xe1', '-', '\x98', '\xd9', '\x9d', 'F', 'A', '\x00', 'V', 'O', '\xb4', '\xa4', '\xb6', 'm', '\xa1', 'S', '\xe4', '8', '\x89', '\xe9', '\xdf', '\xbe', '5', '\x0f', '$', '\xfb', '\x95', 'I', 'n', '{', '\xbe', '$', '\xd0', '\xb7', 'b', '\xe7', '+', '\x84', '=', '\xaa', '\x8a', '', 'U', '\x0f', '\xf4', '\xca', '\xbe', 'd', '\xec', '\xde', 't', '\xae', '\x9a', '\x0c', '\xcc', '\x80', 'S', '\n', 'P', '\x11', '\xe7', '>', '', 'V', '\xb6', '\xf3', '%', '\xc4', '^', '\x1c', '1', '\xdd', '\xde', '\x10', '\xda', '\x08', '\xdb', 'x', ')', 'i', '^', '\x10', 'N', '3', 'g', '\xc1', '\xc9', '\xdc', '\xa9', '\xbc', '\x89', '\r', '\x1b', '\xba', '\x9b', '$', '\x9a', 'L', 'G', '7', '\xed', ':', '>', 'G', '\x19', 'E', '\xc5', '\xf0', '+', '\x94', '\xc0', '=', '\xc5', '\x82', '\xe2', 'U', '\xce', '\x12', '\x92', '\xb3', '\x00', '\xa4', '#', '\xb0', '', '\xe0', '\x9f', '\x83', '\x91', '\xca', '\x8d', '\xf2', 'a', 't', '\xa8', 'E', 'v', '$', '\xcb', '\xcd', '1', '\xdf', '\x98', '\xe3', '\xaf', '\xe8', '\xdd', '\xd9', '\xe5', ';', 'e', '\x10', 'p', '\xa4', '\xff', '2', '\x8b', 'q', '\xff', '\xe7', '\xeb', '\xe9', '\x81', '<', '\n', '\xb2', '\xe5', 'L', '\xf8', '\x97', '1', '\x19', '\xf4', '>', '\x1c', 'J', 'd', 'W', '\xb4', '\x9c', 'G', '\xf0', 'e', '<', '.', ';', '\xdd', '', '\x0f', '\xe4', '\xb1', '+', 'Z', '\xce', 'c', '\xb6', '\x9f', 'G', '\x1d', '\x82', '\x04', 'U', '\x99', '\n', '&', '\x88', '\xa1', '\xed', '\xf4', 'O', '=', 'z', 'l', '\xe9', '\xdf', '\n', '\x9b', '\xdd', '\xda', '', '\x02', 'z', '@', '\xf5', '/', '\x81', 'l', 'l', ' ', '\x83', 'W', '\xf2', '\xd4', '\xde', ',', '\x10', '-', '\xa2', '\x1e', 'C', '4', '\x87', '\x99', 'c', '\xca', '', '\xc9', '4', 'N', '\x80', '\x02', '\xd5', '"', '\xec', '1', 'T', '\xf3', '\xa0', '9', '\xae', '\xb3', 'W', 'r', '\xd5', '\xb1', 'Y', '\xa0', 'Z', 'D', '=', '\x86', 'j', '\x0e', '3', '\xc7', '\xd4', '}', '%', '\xd3', '\xa4', '\xe0', '\x17', '\xb8', '\x16', 'q', '\x8f', '\xe1', '\xba', '\x85', 'Z', 'l', 'V', 'n', '\xae', ':', '\xd3', '^', '\xae', 'W', '\xce', '\xc2', '-', 'i', '\xad', 'u', 'c', 'P', '\xb6', '%', '\xeb', 'q', '\xf2', '\x1d', '\xc4', 'E', '\xf6', 'J', '\xd7', '\xfa', 'N', '\xad', '\xe6', '\xf6', '\x83', 'F', '\xa1', 'S', '\x1a', '\xf4', '\xaf', '\x00', '\xe3', '\x0b', '', 'Q', '\xea', '\xcf', '\x89', '\x08', '|', '\xef', '?', '\xe9', '\xd8', '\xd3', '\xc6', '\xa2', '\xa4', '\xeb', '\xe1', '\x8f', '\xcb', 'L', 'Q', '\xfc', 'u', '\xe2', '\xf9', '\xc2', '\x85', '\xdb', '5', 'I', '\xff', '\xef', '\xd7', '\x9f', 'o', '\x8a', '8', '\xa6', '\x0f', '\xa4', 'b', ',', '}', '\xa8', '\xb4', '\xa7', '\xf0', '\x8d', '?', ':', '\x95', '\xc6', ')', '\xfc', '\xd2', '\xe6', '\x8b', 'I', '&', 'm', 'p', '%', ')', '\x83', '/', '\xf5', 'B', '@', '\xc1', '\x0f', '\xe5', '\xb9', '\xa2', 'w', '\xaf', '\xa1', "'", '\x9a', '\x8c', 'Y', 'y', '\x93', ';', '\x84', '\xd5', 'j', '\xff', 'U', 'O', '$', 'Q', '\xa9', '+', 'c', "'", '\xc4', '\x07', '\xb9', 'W', '7', 'L', 'S', '\xe9', 'J', '!', ',', ';', '\xe1', 'd', '#', '\xa0', '\x8a', 'T', '\x14', '%', ' ', '\xe9', '\x94', '!', '\xbd', '\x08', '\xea', '\xfb', '\xac', '\x89', 'n', '\xe9', '#', '\x85', 'w', '\x89', '>', '\xb2', '\x01', '\x17', 'K', '\x1d', '\x9a', 'p', '\x9d', '\xcc', '\r', '!', '\xf2', '}', '4', '\xb1', ']', '\xb8', '\xff', ']', '\xa4', 'w', 'M', '\xa1', '\x8f', '6', 'S', 'o', '\xa3', '&', '\xaa', '\x12', '\xab', '\xb9', '\xb3', '\x10', '\x85', '\xfa', '\xf1', '\x06', '+', '\x0b', 'u', '\x00', '\xb2', '\xd9', 'f', '\x10', '\x94', '\x8e', '\x7f', 't', '\x02', '4', '\xd9', '\x8e', '\x82', '\xd0', 'M', '4', '\xb8', '\xbb', '\x1a', 'B', 'W', '\xab', 'p', '\xb7', 'L', '\x05', '\x15', '\xbf', '\x08', '1', '\xdf', '\x0b', '1', '/', '\x81', 'P', 'U', '\xa3', '\x88', '1', '\xdb', '\x8b', '1', '+', '\xc1', 'P', '\xf5', '\xbc', '\x88', '\x11', '\xec', '\xc5', '\x08', 'J', '0', 't', '\xa1', '-', '\x82', '\xf0', '\xbd', ' ', '<', '\x01', '\xc9', '\x0f', '\x91', '\xd2', '\xb4', '\xd6', '\xce', 'S', 'm', ';', '\xd4', '\x80', '\x0b', '\x1d', '5', '\xca', '9', '5', '', '\x98', '\xa8', '\x99', '\xdc', '5', '\x90', 'u', 'a', 'n', '#', '\n', '\x0c', '(', '+', '\xa2', '\xfd', 'h', '\xa7', '\xa1', 'F', '\xb6', 'f', '\x16', '\xe9', 'V', '\xab', '\xb9', '\xbb', '\xd7', '\xa7', '{', 'v', 'o', '\x0f', 'G', '6', '\x00', '\r', 'E', '\xcd', '|', 'Y', 'M', '\x1e', "'", '\xe4', ',', '\xdc', ',', '\xa9', 'R', 'l', '5', 'O', '\x01', '\x03', '\xae', 'G', '\x9f', '\xd5', '\xf6', '\x12', 'N', '\xc3', '\xb2', '\x9e', 'U', '\xa6', '\xc8', 'l', '\xce', '\xe1', '\x9c', '\xda', '\xe9', '\xa0', '\xc2', 'i', '\xd8', '\xd9', '\xf5', '\xde', 'y', 'g', '\xe7', '.', '\x91', '\xce', 'w', 'v', '\xdc', '\xc8', ';', '\xdf', '\xdb', '\xc9', '\xa5', '\xc3', '9', '\xb3', '\xf3', '\x85', '\xdb', '\xf9', '\xc1', '\xde', ')', '\xca', '\xce', '{', ';', '+', '\xae', '\xce', '\x8f', '\xf6', 'V', '\x9e', ';', '?', '\xd9', '\x10', '\xcc', '\xa0', 'Z', '\xc5', '#', '\xa8', 'U', '!', '\x05', '\x1a', 'u', 'T', '\x80', '\xae', '8', ']', '@', 'W', 'n', 'l', '\n', '\xc2', '\xd9', '\x84', '\x14', 'v', '\xe4', '\xc7', '\xa1', '\xb0', '3', '?', '\xf8', 'T', '\x00', '\x9b', '\x11', '\xa7', 'F', '\x89', '\xa7', '\x99', '@', 'y', '3', '\xbb', '\x04', '\xc2', '\xf1', '\x9c', '\xd2', 'y', '\xaf', '\xa7', 'F', '\x89', '\x87', '[', '\xff', '\x02', '\r', 'n', '\x1b', 'q']

after decompression: (HEX format) 66756e6374696f6e20636f6c6f72436c6173732865297b73776974636828653d4e756d626572286529297b6361736520435f54555251554f4953453a72657475726e2274757271756f697365223b6361736520435f454d4552414c443a72657475726e22656d6572616c64223b6361736520435f504554455252495645523a72657475726e2270657465727269766572223b6361736520435f57455441535048414c543a72657475726e2277657461737068616c74223b6361736520435f53554e464c4f5745523a72657475726e2273756e666c6f776572223b6361736520435f434152524f543a72657475726e22636172726f74223b6361736520435f414c495a4152494e3a72657475726e22616c697a6172696e223b6361736520435f4e4f4e453a64656661756c743a72657475726e22227d7d66756e6374696f6e20737461727428297b776562736f636b3d6e657720576562536f636b6574282277733a2f2f222b77696e646f772e6c6f636174696f6e2e686f73746e616d652b222f777322292c776562736f636b2e6f6e6f70656e3d66756e6374696f6e2865297b636f6e736f6c652e6c6f672822776562736f636b206f70656e22292c24282223636f6e53746174757322292e616464436c6173732822636f6c6f722d677265656e22292c24282223636f6e53746174757322292e746578742822436f6e6e656374656422297d2c776562736f636b2e6f6e636c6f73653d66756e6374696f6e2865297b636f6e736f6c652e6c6f672822776562736f636b20636c6f736522292c24282223636f6e53746174757322292e72656d6f7665436c6173732822636f6c6f722d677265656e22292c24282223636f6e53746174757322292e616464436c6173732822636f6c6f722d72656422292c24282223636f6e53746174757322292e7465787428224572726f72202f204e6f20436f6e6e656374696f6e22297d2c776562736f636b2e6f6e6572726f723d66756e6374696f6e2865297b636f6e736f6c652e6c6f672865292c24282223636f6e53746174757322292e72656d6f7665436c6173732822636f6c6f722d677265656e22292c24282223636f6e53746174757322292e616464436c6173732822636f6c6f722d72656422292c24282223636f6e53746174757322292e7465787428224572726f72202f204e6f20436f6e6e656374696f6e22297d2c776562736f636b2e6f6e6d6573736167653d66756e6374696f6e2865297b636f6e736f6c652e6c6f672865293b76617220633d4a534f4e2e706172736528652e64617461292c6f3d28646f63756d656e742e626f64792c2222293b73776974636828632e74797065297b636173652055495f544954454c3a646f63756d656e742e7469746c653d632e6c6162656c2c242822236d61696e48656164657222292e68746d6c28632e6c6162656c293b627265616b3b636173652055495f4c4142454c3a24282223726f7722292e617070656e6428223c64697620636c6173733d2774776f20636f6c756d6e732063617264207463656e74657220222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c68352069643d27222b632e69642b22273e222b632e6c6162656c2b223c2f68353e3c6872202f3e3c7370616e2069643d276c222b632e69642b222720636c6173733d276c6162656c206c6162656c2d77726170273e222b632e76616c75652b223c2f7370616e3e3c2f6469763e22293b627265616b3b636173652055495f425554544f4e3a24282223726f7722292e617070656e6428223c64697620636c6173733d276f6e6520636f6c756d6e732063617264207463656e74657220222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c68353e222b632e6c6162656c2b223c2f68353e3c68722f3e3c627574746f6e206f6e6d6f757365646f776e3d27627574746f6e636c69636b28222b632e69642b222c20747275652927206f6e6d6f75736575703d27627574746f6e636c69636b28222b632e69642b222c2066616c736529272069643d27222b632e69642b22273e222b632e76616c75652b223c2f627574746f6e3e3c2f6469763e22292c24282223222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c627574746f6e636c69636b28632e69642c2130297d7d292c24282223222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c627574746f6e636c69636b28632e69642c2131297d7d293b627265616b3b636173652055495f53574954434845523a76617220733d223c6c6162656c2069643d27736c222b632e69642b222720636c6173733d2773776974636820636865636b6564273e222c6e3d223c64697620636c6173733d27696e273e3c696e70757420747970653d27636865636b626f78272069643d2773222b632e69642b2227206f6e436c69636b3d27737769746368657228222b632e69642b222c6e756c6c292720636865636b65643e3c2f6469763e223b2230223d3d632e76616c7565262628733d223c6c6162656c2069643d27736c222b632e69642b222720636c6173733d27737769746368273e222c6e3d223c64697620636c6173733d27696e273e3c696e70757420747970653d27636865636b626f78272069643d2773222b632e69642b2227206f6e436c69636b3d27737769746368657228222b632e69642b222c6e756c6c2927203e3c2f6469763e22292c24282223726f7722292e617070656e6428223c6469762069643d27222b632e69642b222720636c6173733d276f6e6520636f6c756d6e732063617264207463656e74657220222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c68353e222b632e6c6162656c2b223c2f68353e3c68722f3e222b732b6e2b223c2f6c6162656c3e3c2f6469763e22293b627265616b3b636173652055495f435041443a6f3d223c6120636c6173733d27636f6e6669726d27206f6e6d6f757365646f776e3d27706164636c69636b2843454e5445522c20222b632e69642b222c20747275652927206f6e6d6f75736575703d27706164636c69636b2843454e5445522c20222b632e69642b222c2066616c7365292720687265663d2723272069643d277063222b632e69642b22273e53544f503c2f613e223b636173652055495f5041443a24282223726f7722292e617070656e6428223c64697620636c6173733d2774776f20636f6c756d6e732063617264207463656e74657220222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c68353e222b632e6c6162656c2b223c2f68353e3c68722f3e3c6e617620636c6173733d27636f6e74726f6c273e3c756c3e3c6c693e3c61206f6e6d6f757365646f776e3d27706164636c69636b28464f522c20222b632e69642b222c20747275652927206f6e6d6f75736575703d27706164636c69636b28464f522c20222b632e69642b222c2066616c7365292720687265663d2723272069643d277066222b632e69642b22273e5c75323542323c2f613e3c2f6c693e3c6c693e3c61206f6e6d6f757365646f776e3d27706164636c69636b2852494748542c20222b632e69642b222c20747275652927206f6e6d6f75736575703d27706164636c69636b2852494748542c20222b632e69642b222c2066616c7365292720687265663d2723272069643d277072222b632e69642b22273e5c75323542323c2f613e3c2f6c693e3c6c693e3c61206f6e6d6f757365646f776e3d27706164636c69636b284c4546542c20222b632e69642b222c20747275652927206f6e6d6f75736575703d27706164636c69636b284c4546542c20222b632e69642b222c2066616c7365292720687265663d2723272069643d27706c222b632e69642b22273e5c75323542323c2f613e3c2f6c693e3c6c693e3c61206f6e6d6f757365646f776e3d27706164636c69636b284241434b2c20222b632e69642b222c20747275652927206f6e6d6f75736575703d27706164636c69636b284241434b2c20222b632e69642b222c2066616c7365292720687265663d2723272069643d277062222b632e69642b22273e5c75323542323c2f613e3c2f6c693e3c2f756c3e222b6f2b223c2f6e61763e3c2f6469763e22292c242822237066222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b28464f522c632e69642c2130297d7d292c242822237066222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b28464f522c632e69642c2131297d7d292c24282223706c222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b284c4546542c632e69642c2130297d7d292c24282223706c222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b284c4546542c632e69642c2131297d7d292c242822237072222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b2852494748542c632e69642c2130297d7d292c242822237072222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b2852494748542c632e69642c2131297d7d292c242822237062222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b284241434b2c632e69642c2130297d7d292c242822237062222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b284241434b2c632e69642c2131297d7d292c242822237063222b632e6964292e6f6e287b746f75636873746172743a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b2843454e5445522c632e69642c2130297d7d292c242822237063222b632e6964292e6f6e287b746f756368656e643a66756e6374696f6e2865297b652e70726576656e7444656661756c7428292c706164636c69636b2843454e5445522c632e69642c2131297d7d293b627265616b3b63617365205550444154455f4c4142454c3a242822236c222b632e6964292e68746d6c28632e76616c7565293b627265616b3b63617365205550444154455f53574954434845523a2230223d3d632e76616c75653f737769746368657228632e69642c30293a737769746368657228632e69642c31293b627265616b3b636173652055495f534c494445523a24282223726f7722292e617070656e6428223c64697620636c6173733d2774776f20636f6c756d6e732063617264207463656e74657220636172642d736c6964657220222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c68352069643d27222b632e69642b22273e222b632e6c6162656c2b223c2f68353e3c6872202f3e3c6469762069643d27736c222b632e69642b222720636c6173733d27726b6d642d736c6964657220736c696465722d646973637265746520736c696465722d222b636f6c6f72436c61737328632e636f6c6f72292b22273e3c696e70757420747970653d2772616e676527206d696e3d273027206d61783d27313030272076616c75653d27222b632e76616c75652b22273e3c2f6469763e3c2f6469763e22292c24282223726f7722292e617070656e6428223c7363726970743e726b6d645f72616e6765536c69646572282723736c222b632e69642b2227293b3c5c2f7363726970743e22293b627265616b3b63617365205550444154455f534c494445523a736c696465725f6d6f76652824282223736c222b632e6964292c632e76616c75652c22313030222c2131293b627265616b3b64656661756c743a636f6e736f6c652e6572726f722822556e6b6e6f776e2074797065206f72206576656e7422297d7d7d66756e6374696f6e20627574746f6e636c69636b28652c63297b633f776562736f636b2e73656e64282262646f776e3a222b65293a776562736f636b2e73656e6428226275703a222b65297d66756e6374696f6e20706164636c69636b28652c632c6f297b7377697463682865297b636173652043454e5445523a6f3f776562736f636b2e73656e6428227063646f776e3a222b63293a776562736f636b2e73656e642822706375703a222b63293b627265616b3b6361736520464f523a6f3f776562736f636b2e73656e6428227066646f776e3a222b63293a776562736f636b2e73656e642822706675703a222b63293b627265616b3b63617365204241434b3a6f3f776562736f636b2e73656e6428227062646f776e3a222b63293a776562736f636b2e73656e642822706275703a222b63293b627265616b3b63617365204c4546543a6f3f776562736f636b2e73656e642822706c646f776e3a222b63293a776562736f636b2e73656e642822706c75703a222b63293b627265616b3b636173652052494748543a6f3f776562736f636b2e73656e6428227072646f776e3a222b63293a776562736f636b2e73656e642822707275703a222b63297d7d66756e6374696f6e20737769746368657228652c63297b6e756c6c3d3d633f2428222373222b65292e697328223a636865636b656422293f28776562736f636b2e73656e642822736163746976653a222b65292c24282223736c222b65292e616464436c6173732822636865636b65642229293a28776562736f636b2e73656e64282273696e6163746976653a222b65292c24282223736c222b65292e72656d6f7665436c6173732822636865636b65642229293a313d3d633f2824282223736c222b65292e616464436c6173732822636865636b656422292c24282223736c222b65292e70726f702822636865636b6564222c213029293a303d3d6326262824282223736c222b65292e72656d6f7665436c6173732822636865636b656422292c24282223736c222b65292e70726f702822636865636b6564222c213129297d636f6e73742055495f544954454c3d302c55495f4c4142454c3d312c55495f425554544f4e3d322c55495f53574954434845523d332c55495f5041443d342c55495f435041443d352c5550444154455f4c4142454c3d362c5550444154455f53574954434845523d372c55495f534c494445523d382c5550444154455f534c494445523d392c464f523d302c4241434b3d312c4c4546543d322c52494748543d332c43454e5445523d342c435f54555251554f4953453d302c435f454d4552414c443d312c435f504554455252495645523d322c435f57455441535048414c543d332c435f53554e464c4f5745523d342c435f434152524f543d352c435f414c495a4152494e3d362c435f4e4f4e453d373b76617220776562736f636b3b
(ASCII format)
function colorClass(e){switch(e=Number(e)){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_NONE:default:return""}}function start(){websock=new WebSocket("ws://"+window.location.hostname+"/ws"),websock.onopen=function(e){console.log("websock open"),$("#conStatus").addClass("color-green"),$("#conStatus").text("Connected")},websock.onclose=function(e){console.log("websock close"),$("#conStatus").removeClass("color-green"),$("#conStatus").addClass("color-red"),$("#conStatus").text("Error / No Connection")},websock.onerror=function(e){console.log(e),$("#conStatus").removeClass("color-green"),$("#conStatus").addClass("color-red"),$("#conStatus").text("Error / No Connection")},websock.onmessage=function(e){console.log(e);var c=JSON.parse(e.data),o=(document.body,"");switch(c.type){case UI_TITEL:document.title=c.label,$("#mainHeader").html(c.label);break;case UI_LABEL:$("#row").append("

"+c.label+"

"+c.value+"
");break;case UI_BUTTON:$("#row").append("
"+c.label+"

"+c.value+"
"),$("#"+c.id).on({touchstart:function(e){e.preventDefault(),buttonclick(c.id,!0)}}),$("#"+c.id).on({touchend:function(e){e.preventDefault(),buttonclick(c.id,!1)}});break;case UI_SWITCHER:var s="",n="
";"0"==c.value&&(s="",n="
"),$("#row").append("
"+c.label+"

"+s+n+"
");break;case UI_CPAD:o="STOP";case UI_PAD:$("#row").append("
"+c.label+"

"+o+"
"),$("#pf"+c.id).on({touchstart:function(e){e.preventDefault(),padclick(FOR,c.id,!0)}}),$("#pf"+c.id).on({touchend:function(e){e.preventDefault(),padclick(FOR,c.id,!1)}}),$("#pl"+c.id).on({touchstart:function(e){e.preventDefault(),padclick(LEFT,c.id,!0)}}),$("#pl"+c.id).on({touchend:function(e){e.preventDefault(),padclick(LEFT,c.id,!1)}}),$("#pr"+c.id).on({touchstart:function(e){e.preventDefault(),padclick(RIGHT,c.id,!0)}}),$("#pr"+c.id).on({touchend:function(e){e.preventDefault(),padclick(RIGHT,c.id,!1)}}),$("#pb"+c.id).on({touchstart:function(e){e.preventDefault(),padclick(BACK,c.id,!0)}}),$("#pb"+c.id).on({touchend:function(e){e.preventDefault(),padclick(BACK,c.id,!1)}}),$("#pc"+c.id).on({touchstart:function(e){e.preventDefault(),padclick(CENTER,c.id,!0)}}),$("#pc"+c.id).on({touchend:function(e){e.preventDefault(),padclick(CENTER,c.id,!1)}});break;case UPDATE_LABEL:$("#l"+c.id).html(c.value);break;case UPDATE_SWITCHER:"0"==c.value?switcher(c.id,0):switcher(c.id,1);break;case UI_SLIDER:$("#row").append("
"+c.label+"

"),$("#row").append("<script>rkmd_rangeSlider('#sl"+c.id+"');</script>");break;case UPDATE_SLIDER:slider_move($("#sl"+c.id),c.value,"100",!1);break;default:console.error("Unknown type or event")}}}function buttonclick(e,c){c?websock.send("bdown:"+e):websock.send("bup:"+e)}function padclick(e,c,o){switch(e){case CENTER:o?websock.send("pcdown:"+c):websock.send("pcup:"+c);break;case FOR:o?websock.send("pfdown:"+c):websock.send("pfup:"+c);break;case BACK:o?websock.send("pbdown:"+c):websock.send("pbup:"+c);break;case LEFT:o?websock.send("pldown:"+c):websock.send("plup:"+c);break;case RIGHT:o?websock.send("prdown:"+c):websock.send("prup:"+c)}}function switcher(e,c){null==c?$("#s"+e).is(":checked")?(websock.send("sactive:"+e),$("#sl"+e).addClass("checked")):(websock.send("sinactive:"+e),$("#sl"+e).removeClass("checked")):1==c?($("#sl"+e).addClass("checked"),$("#sl"+e).prop("checked",!0)):0==c&&($("#sl"+e).removeClass("checked"),$("#sl"+e).prop("checked",!1))}const UI_TITEL=0,UI_LABEL=1,UI_BUTTON=2,UI_SWITCHER=3,UI_PAD=4,UI_CPAD=5,UPDATE_LABEL=6,UPDATE_SWITCHER=7,UI_SLIDER=8,UPDATE_SLIDER=9,FOR=0,BACK=1,LEFT=2,RIGHT=3,CENTER=4,C_TURQUOISE=0,C_EMERALD=1,C_PETERRIVER=2,C_WETASPHALT=3,C_SUNFLOWER=4,C_CARROT=5,C_ALIZARIN=6,C_NONE=7;var websock;

Enhancements suggestion

ESPUI is very convenient. Thanks a lot!
I am using ESPUI for a project with more than 12 widgets => great results with limited programming effort.

Here are some suggestions for enhancements:

  • returning the widget ID in ESPUI.label(), ESPUI.button(), etc ... (will save call to getIdByLabel())
  • support for multi-line label text
  • automatic label resizing to display long text (currently long text is exceeding the widget contour)
  • ability to anchor widgets to cells in a 2D grid layout
  • widget for text/numeric value input

I am currently analyzing ESPUI code to see how I can contribute to these enhancements.
Frederic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.