1
0
mirror of https://github.com/s00500/ESPUI.git synced 2025-07-04 11:20:19 +00:00

40 Commits

Author SHA1 Message Date
16adba2ec3 Bump Version 2022-01-08 17:37:50 +01:00
e3638beb14 Some example improvements by @thomastech
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2022-01-08 17:31:39 +01:00
29964a83f2 Merge pull request #145 from iangray001/master
Add inline styles to documentation
2022-01-05 22:53:53 +00:00
e1fe13bac6 Implement LITTLEFS as requested by @thomastech in #144
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2022-01-04 11:35:43 +01:00
3cbae2ff1b Reformat examples
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2022-01-04 11:20:04 +01:00
cdd0f5bac3 Note that images can be displayed with Labels 2022-01-03 20:19:24 +00:00
6a7cfd857c Update documentation 2022-01-03 16:21:39 +00:00
2a5815c579 Fix signed (int) being compared against unsigned (size_t)
This used to emit two warnings about signedness comparison, so is updated to use
an appropriate type.
2022-01-03 15:46:38 +00:00
7e5331d54f Realign with upstream 2022-01-03 15:39:48 +00:00
0ab401c3b1 Merge branch 'master' of github.com:s00500/ESPUI 2022-01-03 15:18:49 +00:00
232ca3ead4 Support for dynamic custom inline styling.
Adds two functions in ESPUI.h:
setPanelStyle()
setElementStyle()
These allow for custom inline CSS styles to be applied to the panel and to
the specific UI element repectively.

For example:

```
char stylecol1[30]
sprintf(stylecol1, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
ESPUI.setPanelStyle(switch1, stylecol1);
```
This will set the panel of the given control to a random hex colour.

This is supported by both the initial UI message, and by control update messages, so you
can change these styles dynamically in response to other events.

setElementStyle() is not perfect. Because CSS inline styles can only style one specific
DOM element, for controls made up of multiple elements (like the "pad") this is limited.
I have tried to make an appropriate choice for each supported control.
2022-01-03 13:06:55 +01:00
06460fcc4d Chunk updates 2022-01-03 13:06:33 +01:00
8331255355 Add feedback to buttons when being pessed. One way to address #110. 2022-01-03 13:06:33 +01:00
6800f0c208 Fixes #122 2022-01-03 13:06:33 +01:00
6f744a7995 Update minified and header files for previous commit 2022-01-03 13:05:53 +01:00
c5846ca644 Fixes #127 2022-01-03 13:05:53 +01:00
19e187a280 Add PIO Example
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2022-01-03 13:03:07 +01:00
ec1862cfe6 Support for dynamic custom inline styling.
Adds two functions in ESPUI.h:
setPanelStyle()
setElementStyle()
These allow for custom inline CSS styles to be applied to the panel and to
the specific UI element repectively.

For example:

```
char stylecol1[30]
sprintf(stylecol1, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
ESPUI.setPanelStyle(switch1, stylecol1);
```
This will set the panel of the given control to a random hex colour.

This is supported by both the initial UI message, and by control update messages, so you
can change these styles dynamically in response to other events.

setElementStyle() is not perfect. Because CSS inline styles can only style one specific
DOM element, for controls made up of multiple elements (like the "pad") this is limited.
I have tried to make an appropriate choice for each supported control.
2022-01-02 21:56:32 +00:00
78317ce5f2 Chunk updates 2022-01-01 22:04:32 +00:00
1d78608786 Add feedback to buttons when being pessed. One way to address #110. 2021-12-29 23:01:01 +00:00
aaea0fb877 Fixes #122 2021-12-29 17:52:03 +00:00
1df56772d9 Fixes #136 and also severe bug in addControl 2021-12-29 16:37:48 +00:00
eebefd915c Update minified and header files for previous commit 2021-12-29 10:29:24 +00:00
777ceb2bed Fixes #127 2021-12-28 17:13:25 +00:00
c66f528702 Send visibility
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2021-10-29 19:47:46 +02:00
aa03c1683d Add Port Option
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2021-10-29 19:37:56 +02:00
6b3056ab31 Merge pull request #131 from Noctr/master 2021-08-10 08:17:29 +02:00
95d13ec5a9 Update ESPUI.h 2021-08-06 21:40:10 +07:00
de0c74ab4b Update ESPUI.h 2021-08-06 21:33:53 +07:00
1a8407a0ec Update ESPUI.h 2021-08-01 23:54:50 +07:00
5bec1ed988 Update dataControlsJS.h 2021-08-01 23:50:26 +07:00
98ec85ea8b Update controls.min.js 2021-08-01 23:45:49 +07:00
6a9c989766 Update controls.js 2021-08-01 23:38:13 +07:00
0587918621 Merge pull request #109 from A-damW/master
Update README.md
2021-02-06 09:42:08 +01:00
48826caee6 Merge pull request #114 from tecteun/master
slider sends (browser dependent) lots of events, throttle using only …
2021-02-06 09:41:26 +01:00
9ab8a84ff0 slider sends (browser dependent) lots of events, throttle using only unique values. 2021-02-05 22:03:02 +00:00
d12da60df4 Update README.md
Minor typo, line 107, "to to" > "to do"
2021-01-10 08:20:16 +00:00
8cdedaf3cb Merge pull request #106 from marcusmiess/master-fix-pad-arrows
Fix for pad arrows
2021-01-02 10:10:54 +01:00
02d981cc2b Changed the ascii arrow to the HTML equivalent. Fixes the problem, where the pad arrow strings got broken. 2021-01-02 00:23:13 +01:00
4827688635 Version 2.0.2
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
2020-10-19 08:57:59 +02:00
19 changed files with 1853 additions and 699 deletions

View File

@ -32,6 +32,7 @@ The Library runs fine on any kind of **ESP8266** and **ESP32** (NodeMCU Boards,
- OptionList by @eringerli
- Public Access to ESPAsyncServer
- Graph Widget (Persist save graph in local storage #10)
- Inline CSS styles by @iangray001
## Further Roadmap
@ -49,6 +50,7 @@ This library is dependent on the following libraries to function properly.
- (_For ESP8266_) [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP)
- (_For ESP32_) [AsyncTCP](https://github.com/me-no-dev/AsyncTCP)
- (_For ESP32_) [lorol/LittleFS_esp32](https://github.com/lorol/LITTLEFS)
## How to Install
@ -89,13 +91,13 @@ Go to Sketch>Include Library>Add .zip Library> Select the Downloaded .zip File.
## Getting started
ESPUI serves several files to the browser to build up its web interface. This
can be achieved in 2 ways: _PROGMEM_ or _SPIFFS_
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 SPIFFS filesystem on the ESP. There are now two ways to
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()`
@ -104,7 +106,7 @@ function `ESPUI.prepareFileSystem()`
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 to this again when there is a library update, or when you want to
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
@ -214,7 +216,17 @@ on creation and a initial value. The name is not changeable once the UI
initialised.
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
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
@ -296,7 +308,7 @@ Then all widgets for the tab need to be added to it by specifying the tab as the
### Initialisation of the UI
After all the elements are configured you can use `ESPUI.begin("Some Title");`
to start the UI interface. (Or `ESPUI.beginSPIFFS("Some Title");` respectively)
to start the UI interface. (Or `ESPUI.beginLITTLEFS("Some Title");` respectively)
Make sure you setup a working network connection or AccesPoint **before** (See
gui.ino example). The web interface can then be used from multiple devices at once and
also shows an connection status in the top bar.
@ -342,6 +354,43 @@ If you have many different widgets it might be necessary to adjust the JSON Buff
ESPUI.begin("ESPUI Control");
```
### 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](docs/inlinestyles.gif)
Note: The images in this example are formed by setting a Label to contain an `<img>` tag:
```
ESPUI.addControl(ControlType::Label, "Label", "<img src='path/to/image'>", ControlColor::Peterriver);
```
# Notes for Development
If you want to work on the HTML/CSS/JS files, do make changes in the _data_

View File

@ -400,6 +400,11 @@ button {
background-color: #999999;
}
button:active {
background-color: #666666;
transform: translateX(4px) translateY(4px);
}
/* Main Head Part
*/

File diff suppressed because one or more lines are too long

155
data/js/controls.js vendored
View File

@ -2,6 +2,8 @@ const UI_INITIAL_GUI = 200;
const UI_RELOAD = 201;
const UPDATE_OFFSET = 100;
const UI_EXTEND_GUI = 210;
const UI_TITEL = 0;
const UI_PAD = 1;
@ -230,6 +232,10 @@ function start() {
var data = JSON.parse(evt.data);
var e = document.body;
var center = "";
panelStyle = data.hasOwnProperty('panelStyle') ? " style='" + data.panelStyle + "'" : "";
elementStyle = data.hasOwnProperty('elementStyle') ? " style='" + data.elementStyle + "'" : "";
switch (data.type) {
case UI_INITIAL_GUI:
// Clear current elements
@ -247,6 +253,16 @@ function start() {
handleEvent(fauxEvent);
});
break;
case UI_EXTEND_GUI:
data.controls.forEach(element => {
var fauxEvent = {
data: JSON.stringify(element),
};
handleEvent(fauxEvent);
});
break;
case UI_RELOAD:
window.location.reload();
break;
@ -263,10 +279,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -274,11 +291,12 @@ function start() {
"</h5><hr/>" +
"<span id='l" +
data.id +
"' class='label label-wrap'>" +
"' " + elementStyle + " class='label label-wrap'>" +
data.value +
"</span>" +
"</div>"
);
}
break;
case UI_BUTTON:
@ -288,10 +306,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='one columns card tcenter " +
"' " + panelStyle + " class='one columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -299,7 +318,7 @@ function start() {
"</h5><hr/>" +
"<button id='btn" +
data.id +
"' " +
"' " + elementStyle + " " +
"onmousedown='buttonclick(" +
data.id +
", true)' " +
@ -319,6 +338,7 @@ function start() {
buttonclick(data.id, false);
},
});
}
break;
case UI_SWITCHER:
@ -328,10 +348,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='one columns card tcenter " +
"' " + panelStyle + " class='one columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -339,7 +360,7 @@ function start() {
"</h5><hr/>" +
"<label id='sl" +
data.id +
"' class='switch " +
"' " + elementStyle + " class='switch " +
(data.value == "1" ? "checked" : "") +
"'>" +
"<div class='in'><input type='checkbox' id='s" +
@ -353,6 +374,7 @@ function start() {
"</div>"
);
switcher(data.id, data.value);
}
break;
case UI_CPAD:
@ -363,10 +385,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -380,28 +403,28 @@ function start() {
data.id +
", false)' id='pf" +
data.id +
"'></a></li>" +
"'>&#9650;</a></li>" +
"<li><a onmousedown='padclick(RIGHT, " +
data.id +
", true)' onmouseup='padclick(RIGHT, " +
data.id +
", false)' id='pr" +
data.id +
"'></a></li>" +
"'>&#9650;</a></li>" +
"<li><a onmousedown='padclick(LEFT, " +
data.id +
", true)' onmouseup='padclick(LEFT, " +
data.id +
", false)' id='pl" +
data.id +
"'></a></li>" +
"'>&#9650;</a></li>" +
"<li><a onmousedown='padclick(DOWN, " +
data.id +
", true)' onmouseup='padclick(DOWN, " +
data.id +
", false)' id='pb" +
data.id +
"'></a></li>" +
"'>&#9650;</a></li>" +
"</ul>" +
(data.type == UI_CPAD
? "<a class='confirm' onmousedown='padclick(CENTER," +
@ -466,7 +489,7 @@ function start() {
padclick(CENTER, data.id, false);
},
});
}
break;
//https://codepen.io/seanstopnik/pen/CeLqA
@ -477,10 +500,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter card-slider " +
"' " + panelStyle + " class='two columns card tcenter card-slider " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -491,7 +515,7 @@ function start() {
data.id +
"' type='range' min='0' max='100' value='" +
data.value +
"' class='range-slider__range'>" +
"' " + elementStyle + " class='range-slider__range'>" +
"<span class='range-slider__value'>" +
data.value +
"</span>" +
@ -499,6 +523,7 @@ function start() {
"</div>"
);
rangeSlider(!sliderContinuous);
}
break;
case UI_NUMBER:
@ -508,16 +533,17 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
data.label +
"</h5><hr/>" +
"<input style='color:black;' id='num" +
"<input style='color:black;' " + elementStyle + " id='num" +
data.id +
"' type='number' value='" +
data.value +
@ -526,6 +552,7 @@ function start() {
")' />" +
"</div>"
);
}
break;
case UI_TEXT_INPUT:
@ -535,16 +562,17 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
data.label +
"</h5><hr/>" +
"<input style='color:black;' id='text" +
"<input style='color:black;' " + elementStyle + " id='text" +
data.id +
"' value='" +
data.value +
@ -553,9 +581,11 @@ function start() {
")' />" +
"</div>"
);
}
break;
case UI_TAB:
if (data.visible) {
$("#tabsnav").append(
"<li><a onmouseup='tabclick(" + data.id + ")' href='#tab" + data.id + "'>" + data.value + "</a></li>"
);
@ -574,6 +604,7 @@ function start() {
}
e.preventDefault();
});
}
break;
case UI_SELECT:
@ -583,22 +614,24 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
data.label +
"</h5><hr/>" +
"<select style='color:black;' id='select" +
"<select style='color:black;' " + elementStyle + " id='select" +
data.id +
"' onchange='selectchange(" +
data.id +
")' />" +
"</div>"
);
}
break;
case UI_OPTION:
@ -651,10 +684,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -671,6 +705,7 @@ function start() {
);
graphData[data.id] = restoreGraphData(data.id);
renderGraphSvg(graphData[data.id], "graph" + data.id);
}
break;
case ADD_GRAPH_POINT:
var ts = Math.round(new Date().getTime() / 1000);
@ -690,10 +725,11 @@ function start() {
} else {
parent = $("#row");
}
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -708,6 +744,7 @@ function start() {
")' />" +
"</div>"
);
}
break;
case UI_ACCEL:
@ -719,10 +756,11 @@ function start() {
parent = $("#row");
}
hasAccel = true;
if (data.visible) {
parent.append(
"<div id='id" +
data.id +
"' class='two columns card tcenter " +
"' " + panelStyle + " class='two columns card tcenter " +
colorClass(data.color) +
"'>" +
"<h5>" +
@ -739,30 +777,49 @@ function start() {
);
requestOrientationPermission();
}
break;
case UPDATE_LABEL:
$("#l" + data.id).html(data.value);
if(data.hasOwnProperty('elementStyle')) {
$("#l" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_SWITCHER:
switcher(data.id, data.value == "0" ? 0 : 1);
if(data.hasOwnProperty('elementStyle')) {
$("#sl" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_SLIDER:
slider_move($("#id" + data.id), data.value, "100", false);
if(data.hasOwnProperty('elementStyle')) {
$("#sl" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_NUMBER:
$("#num" + data.id).val(data.value);
if(data.hasOwnProperty('elementStyle')) {
$("#num" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_TEXT_INPUT:
$("#text" + data.id).val(data.value);
if(data.hasOwnProperty('elementStyle')) {
$("#text" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_SELECT:
$("#select" + data.id).val(data.value);
if(data.hasOwnProperty('elementStyle')) {
$("#select" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_BUTTON:
@ -771,6 +828,9 @@ function start() {
break;
case UPDATE_GAUGE:
$("#gauge" + data.id).val(data.value);
if(data.hasOwnProperty('elementStyle')) {
$("#gauge" + data.id).attr("style", data.elementStyle);
}
break;
case UPDATE_ACCEL:
break;
@ -782,6 +842,11 @@ function start() {
if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
var element = $("#id" + data.id);
if(data.hasOwnProperty('panelStyle')) {
$("#id" + data.id).attr("style", data.panelStyle);
}
if (data.type == UPDATE_SLIDER) {
element.removeClass(
"slider-turquoise slider-emerald slider-peterriver slider-wetasphalt slider-sunflower slider-carrot slider-alizarin"
@ -794,6 +859,11 @@ function start() {
element.addClass(colorClass(data.color));
}
}
$(".range-slider__range").each(function(){
$(this)[0].value = $(this).attr("value");
$(this).next().html($(this).attr("value"));
});
};
websock.onmessage = handleEvent;
@ -873,31 +943,24 @@ function switcher(number, state) {
}
var rangeSlider = function (isDiscrete) {
var slider = $(".range-slider"),
range = $(".range-slider__range"),
value = $(".range-slider__value");
var range = $(".range-slider__range");
var slidercb = function() {
sliderchange($(this).attr("id").replace(/^\D+/g, ""));
};
slider.each(function () {
value.each(function () {
var value = $(this).prev().attr("value");
$(this).html(value);
});
range.on({input: function() {
$(this).next().html(this.value)}
});
if (!isDiscrete) {
range.on({
input: function () {
sliderchange($(this).attr("id").replace(/^\D+/g, ""));
},
});
} else {
range.on({
input: function () {
$(this).next().html(this.value);
},
change: function () {
sliderchange($(this).attr("id").replace(/^\D+/g, ""));
},
});
range.each(function() {
$(this).next().html(this.value);
if($(this).attr("callbackSet") != "true") {
if (!isDiscrete) {
$(this).on({input: slidercb}); //input fires when dragging
} else {
$(this).on({change: slidercb}); //change fires only once released
}
$(this).attr("callbackSet", "true");
}
});
};

File diff suppressed because one or more lines are too long

BIN
docs/inlinestyles.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

View File

@ -2,7 +2,7 @@
#include <ESPUI.h>
const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
IPAddress apIP(192, 168, 4, 1);
DNSServer dnsServer;
#if defined(ESP32)
@ -11,252 +11,289 @@ DNSServer dnsServer;
#include <ESP8266WiFi.h>
#endif
const char *ssid = "ESPUI";
const char *password = "espui";
const char *hostname = "espui";
const char* ssid = "ESPUI";
const char* password = "espui";
const char* hostname = "espui";
uint16_t status;
uint16_t button1;
uint16_t millisLabelId;
uint16_t switchOne;
void numberCall( Control* sender, int type ) {
Serial.println( sender->value );
void numberCall(Control* sender, int type)
{
Serial.println(sender->value);
}
void textCall(Control *sender, int type) {
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
void textCall(Control* sender, int type)
{
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void slider(Control *sender, int type) {
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
void slider(Control* sender, int type)
{
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void buttonCallback(Control *sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Button DOWN");
break;
void buttonCallback(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Button UP");
break;
}
case B_UP:
Serial.println("Button UP");
break;
}
}
void buttonExample(Control *sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Status: Start");
ESPUI.updateControlValue(status, "Start");
void buttonExample(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Status: Start");
ESPUI.updateControlValue(status, "Start");
ESPUI.getControl(button1)->color = ControlColor::Carrot;
ESPUI.updateControl(button1);
break;
ESPUI.getControl(button1)->color = ControlColor::Carrot;
ESPUI.updateControl(button1);
break;
case B_UP:
Serial.println("Status: Stop");
ESPUI.updateControlValue(status, "Stop");
case B_UP:
Serial.println("Status: Stop");
ESPUI.updateControlValue(status, "Stop");
ESPUI.getControl(button1)->color = ControlColor::Peterriver;
ESPUI.updateControl(button1);
break;
}
ESPUI.getControl(button1)->color = ControlColor::Peterriver;
ESPUI.updateControl(button1);
break;
}
}
void padExample(Control *sender, int value) {
switch (value) {
case P_LEFT_DOWN:
Serial.print("left down");
break;
void padExample(Control* sender, int value)
{
switch (value)
{
case P_LEFT_DOWN:
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
}
case P_CENTER_UP:
Serial.print("center up");
break;
}
Serial.print(" ");
Serial.println(sender->id);
Serial.print(" ");
Serial.println(sender->id);
}
void switchExample(Control *sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
void switchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
Serial.print(" ");
Serial.println(sender->id);
}
void selectExample(Control *sender, int value) {
Serial.print("Select: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
void selectExample(Control* sender, int value)
{
Serial.print("Select: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void otherSwitchExample(Control *sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
void otherSwitchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
Serial.print(" ");
Serial.println(sender->id);
}
void setup(void) {
ESPUI.setVerbosity(Verbosity::VerboseJSON);
Serial.begin(115200);
void setup(void)
{
ESPUI.setVerbosity(Verbosity::VerboseJSON);
Serial.begin(115200);
#if defined(ESP32)
WiFi.setHostname(hostname);
WiFi.setHostname(hostname);
#else
WiFi.hostname(hostname);
WiFi.hostname(hostname);
#endif
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
{
uint8_t timeout = 10;
{
uint8_t timeout = 10;
// Wait for connection, 5s timeout
do {
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// Wait for connection, 5s timeout
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED) {
Serial.print("\n\nCreating hotspot");
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED)
{
Serial.print("\n\nCreating hotspot");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(ssid);
WiFi.mode(WIFI_AP);
delay(100);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
#if defined(ESP32)
uint32_t chipid = 0;
for (int i = 0; i < 17; i = i + 8)
{
chipid |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
#else
uint32_t chipid = ESP.getChipId();
#endif char ap_ssid[25];
snprintf(ap_ssid, 26, "ESPUI-%08X", chipid);
WiFi.softAP(ap_ssid);
timeout = 5;
timeout = 5;
do {
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
}
}
}
dnsServer.start(DNS_PORT, "*", apIP);
dnsServer.start(DNS_PORT, "*", apIP);
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
uint16_t select1 = ESPUI.addControl(ControlType::Select, "Select:", "", ControlColor::Alizarin, Control::noParent, &selectExample);
uint16_t select1 = ESPUI.addControl(
ControlType::Select, "Select:", "", ControlColor::Alizarin, Control::noParent, &selectExample);
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);
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);
ESPUI.addControl(ControlType::Text, "Text Test:", "a Text Field", ControlColor::Alizarin, Control::noParent, &textCall);
ESPUI.addControl(
ControlType::Text, "Text Test:", "a Text Field", ControlColor::Alizarin, Control::noParent, &textCall);
millisLabelId = ESPUI.addControl(ControlType::Label, "Millis:", "0", ControlColor::Emerald, Control::noParent);
button1 = ESPUI.addControl(ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, Control::noParent, &buttonCallback);
ESPUI.addControl(ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, Control::noParent, &buttonExample);
ESPUI.addControl(ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, Control::noParent, &padExample);
ESPUI.addControl(ControlType::Pad, "Pad without center", "", ControlColor::Carrot, Control::noParent, &padExample);
switchOne = ESPUI.addControl(ControlType::Switcher, "Switch one", "", ControlColor::Alizarin, Control::noParent, &switchExample);
ESPUI.addControl(ControlType::Switcher, "Switch two", "", ControlColor::None, Control::noParent, &otherSwitchExample);
ESPUI.addControl(ControlType::Slider, "Slider one", "30", ControlColor::Alizarin, Control::noParent, &slider);
ESPUI.addControl(ControlType::Slider, "Slider two", "100", ControlColor::Alizarin, Control::noParent, &slider);
ESPUI.addControl(ControlType::Number, "Number:", "50", ControlColor::Alizarin, Control::noParent, &numberCall);
millisLabelId = ESPUI.addControl(ControlType::Label, "Millis:", "0", ControlColor::Emerald, Control::noParent);
button1 = ESPUI.addControl(
ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, Control::noParent, &buttonCallback);
ESPUI.addControl(
ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, Control::noParent, &buttonExample);
ESPUI.addControl(
ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, Control::noParent, &padExample);
ESPUI.addControl(ControlType::Pad, "Pad without center", "", ControlColor::Carrot, Control::noParent, &padExample);
switchOne = ESPUI.addControl(
ControlType::Switcher, "Switch one", "", ControlColor::Alizarin, Control::noParent, &switchExample);
ESPUI.addControl(
ControlType::Switcher, "Switch two", "", ControlColor::None, Control::noParent, &otherSwitchExample);
ESPUI.addControl(ControlType::Slider, "Slider one", "30", ControlColor::Alizarin, Control::noParent, &slider);
ESPUI.addControl(ControlType::Slider, "Slider two", "100", ControlColor::Alizarin, Control::noParent, &slider);
ESPUI.addControl(ControlType::Number, "Number:", "50", ControlColor::Alizarin, Control::noParent, &numberCall);
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from SPIFFS use ESPUI.beginSPIFFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from LITTLEFS use ESPUI.beginLITTLEFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
ESPUI.begin("ESPUI Control");
ESPUI.begin("ESPUI Control");
}
void loop(void) {
dnsServer.processNextRequest();
void loop(void)
{
dnsServer.processNextRequest();
static long oldTime = 0;
static bool testSwitchState = false;
static long oldTime = 0;
static bool testSwitchState = false;
if (millis() - oldTime > 5000) {
ESPUI.updateControlValue(millisLabelId, String(millis()));
testSwitchState = !testSwitchState;
ESPUI.updateControlValue(switchOne, testSwitchState ? "1" : "0");
if (millis() - oldTime > 5000)
{
ESPUI.updateControlValue(millisLabelId, String(millis()));
testSwitchState = !testSwitchState;
ESPUI.updateControlValue(switchOne, testSwitchState ? "1" : "0");
oldTime = millis();
}
oldTime = millis();
}
}

View File

@ -2,7 +2,7 @@
#include <ESPUI.h>
const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
IPAddress apIP(192, 168, 4, 1);
DNSServer dnsServer;
#if defined(ESP32)
@ -11,238 +11,270 @@ DNSServer dnsServer;
#include <ESP8266WiFi.h>
#endif
const char *ssid = "ESPUI";
const char *password = "espui";
const char* ssid = "ESPUI";
const char* password = "espui";
const char *hostname = "espui";
const char* hostname = "espui";
int statusLabelId;
int graphId;
int millisLabelId;
int testSwitchId;
void numberCall(Control *sender, int type) { Serial.println(sender->value); }
void textCall(Control *sender, int type) {
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
void numberCall(Control* sender, int type)
{
Serial.println(sender->value);
}
void slider(Control *sender, int type) {
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
// Like all Control Values in ESPUI slider values are Strings. To use them as int simply do this:
int sliderValueWithOffset = sender->value.toInt() + 100;
Serial.print("SliderValue with offset");
Serial.println(sliderValueWithOffset);
void textCall(Control* sender, int type)
{
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void buttonCallback(Control *sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Button UP");
break;
}
void slider(Control* sender, int type)
{
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
// Like all Control Values in ESPUI slider values are Strings. To use them as int simply do this:
int sliderValueWithOffset = sender->value.toInt() + 100;
Serial.print("SliderValue with offset");
Serial.println(sliderValueWithOffset);
}
void buttonExample(Control *sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Status: Start");
ESPUI.print(statusLabelId, "Start");
break;
void buttonCallback(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Status: Stop");
ESPUI.print(statusLabelId, "Stop");
break;
}
}
void padExample(Control *sender, int value) {
switch (value) {
case P_LEFT_DOWN:
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
}
Serial.print(" ");
Serial.println(sender->id);
case B_UP:
Serial.println("Button UP");
break;
}
}
void switchExample(Control *sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
void buttonExample(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Status: Start");
ESPUI.print(statusLabelId, "Start");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
case B_UP:
Serial.println("Status: Stop");
ESPUI.print(statusLabelId, "Stop");
break;
}
}
void padExample(Control* sender, int value)
{
switch (value)
{
case P_LEFT_DOWN:
Serial.print("left down");
break;
Serial.print(" ");
Serial.println(sender->id);
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
}
Serial.print(" ");
Serial.println(sender->id);
}
void otherSwitchExample(Control *sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
void switchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
Serial.print(" ");
Serial.println(sender->id);
}
void setup(void) {
ESPUI.setVerbosity(Verbosity::VerboseJSON);
Serial.begin(115200);
void otherSwitchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
}
void setup(void)
{
ESPUI.setVerbosity(Verbosity::VerboseJSON);
Serial.begin(115200);
#if defined(ESP32)
WiFi.setHostname(hostname);
WiFi.setHostname(hostname);
#else
WiFi.hostname(hostname);
WiFi.hostname(hostname);
#endif
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
{
uint8_t timeout = 10;
{
uint8_t timeout = 10;
// Wait for connection, 5s timeout
do {
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// Wait for connection, 5s timeout
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED) {
Serial.print("\n\nCreating hotspot");
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED)
{
Serial.print("\n\nCreating hotspot");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(ssid);
WiFi.mode(WIFI_AP);
delay(100);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
#if defined(ESP32)
uint32_t chipid = 0;
for (int i = 0; i < 17; i = i + 8)
{
chipid |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
#else
uint32_t chipid = ESP.getChipId();
#endif
char ap_ssid[25];
snprintf(ap_ssid, 26, "ESPUI-%08X", chipid);
WiFi.softAP(ap_ssid);
timeout = 5;
timeout = 5;
do {
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
}
}
}
dnsServer.start(DNS_PORT, "*", apIP);
dnsServer.start(DNS_PORT, "*", apIP);
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");
ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press");
ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press");
ESPUI.padWithCenter("Pad with center", &padExample, ControlColor::Sunflower);
ESPUI.pad("Pad without center", &padExample, ControlColor::Carrot);
testSwitchId = ESPUI.switcher("Switch one", &switchExample, ControlColor::Alizarin, false);
ESPUI.switcher("Switch two", &otherSwitchExample, ControlColor::None, true);
ESPUI.slider("Slider one", &slider, ControlColor::Alizarin, 30);
ESPUI.slider("Slider two", &slider, ControlColor::None, 100);
ESPUI.text("Text Test:", &textCall, ControlColor::Alizarin, "a Text Field");
ESPUI.number("Numbertest", &numberCall, ControlColor::Alizarin, 5, 0, 10);
statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");
ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press");
ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press");
ESPUI.padWithCenter("Pad with center", &padExample, ControlColor::Sunflower);
ESPUI.pad("Pad without center", &padExample, ControlColor::Carrot);
testSwitchId = ESPUI.switcher("Switch one", &switchExample, ControlColor::Alizarin, false);
ESPUI.switcher("Switch two", &otherSwitchExample, ControlColor::None, true);
ESPUI.slider("Slider one", &slider, ControlColor::Alizarin, 30);
ESPUI.slider("Slider two", &slider, ControlColor::None, 100);
ESPUI.text("Text Test:", &textCall, ControlColor::Alizarin, "a Text Field");
ESPUI.number("Numbertest", &numberCall, ControlColor::Alizarin, 5, 0, 10);
graphId = ESPUI.graph("Graph Test", ControlColor::Wetasphalt);
graphId = ESPUI.graph("Graph Test", ControlColor::Wetasphalt);
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from SPIFFS use ESPUI.beginSPIFFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from LITTLEFS use ESPUI.beginLITTLEFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
ESPUI.begin("ESPUI Control");
ESPUI.begin("ESPUI Control");
}
void loop(void) {
dnsServer.processNextRequest();
void loop(void)
{
dnsServer.processNextRequest();
static long oldTime = 0;
static bool testSwitchState = false;
static long oldTime = 0;
static bool testSwitchState = false;
if (millis() - oldTime > 5000) {
ESPUI.print(millisLabelId, String(millis()));
if (millis() - oldTime > 5000)
{
ESPUI.print(millisLabelId, String(millis()));
ESPUI.addGraphPoint(graphId, random(1, 50));
ESPUI.addGraphPoint(graphId, random(1, 50));
testSwitchState = !testSwitchState;
ESPUI.updateSwitcher(testSwitchId, testSwitchState);
testSwitchState = !testSwitchState;
ESPUI.updateSwitcher(testSwitchId, testSwitchState);
oldTime = millis();
}
oldTime = millis();
}
}

View File

@ -2,7 +2,7 @@
#include <ESPUI.h>
const byte DNS_PORT = 53;
IPAddress apIP( 192, 168, 1, 1 );
IPAddress apIP(192, 168, 4, 1);
DNSServer dnsServer;
#if defined(ESP32)
@ -19,244 +19,279 @@ uint16_t button1;
uint16_t switchOne;
uint16_t status;
void numberCall( Control* sender, int type ) {
Serial.println( sender->value );
void numberCall(Control* sender, int type)
{
Serial.println(sender->value);
}
void textCall( Control* sender, int type ) {
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println( sender->value );}
void textCall(Control* sender, int type)
{
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void slider( Control* sender, int type ) {
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println( sender->value );}
void slider(Control* sender, int type)
{
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void buttonCallback( Control* sender, int type ) {
switch ( type ) {
void buttonCallback(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println( "Button DOWN" );
break;
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println( "Button UP" );
break;
}
Serial.println("Button UP");
break;
}
}
void buttonExample( Control* sender, int type ) {
switch ( type ) {
void buttonExample(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println( "Status: Start" );
ESPUI.updateControlValue( status, "Start" );
Serial.println("Status: Start");
ESPUI.updateControlValue(status, "Start");
ESPUI.getControl( button1 )->color = ControlColor::Carrot;
ESPUI.updateControl( button1 );
break;
ESPUI.getControl(button1)->color = ControlColor::Carrot;
ESPUI.updateControl(button1);
break;
case B_UP:
Serial.println( "Status: Stop" );
ESPUI.updateControlValue( status, "Stop" );
Serial.println("Status: Stop");
ESPUI.updateControlValue(status, "Stop");
ESPUI.getControl( button1 )->color = ControlColor::Peterriver;
ESPUI.updateControl( button1 );
break;
}
ESPUI.getControl(button1)->color = ControlColor::Peterriver;
ESPUI.updateControl(button1);
break;
}
}
void padExample( Control* sender, int value ) {
switch ( value ) {
void padExample(Control* sender, int value)
{
switch (value)
{
case P_LEFT_DOWN:
Serial.print( "left down" );
break;
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print( "left up" );
break;
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print( "right down" );
break;
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print( "right up" );
break;
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print( "for down" );
break;
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print( "for up" );
break;
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print( "back down" );
break;
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print( "back up" );
break;
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print( "center down" );
break;
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print( "center up" );
break;
}
Serial.print("center up");
break;
}
Serial.print( " " );
Serial.println( sender->id );
Serial.print(" ");
Serial.println(sender->id);
}
void switchExample( Control* sender, int value ) {
switch ( value ) {
void switchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print( "Active:" );
break;
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print( "Inactive" );
break;
}
Serial.print("Inactive");
break;
}
Serial.print( " " );
Serial.println( sender->id );
Serial.print(" ");
Serial.println(sender->id);
}
void selectExample( Control* sender, int value ) {
Serial.print("Select: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println( sender->value );
void selectExample(Control* sender, int value)
{
Serial.print("Select: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void otherSwitchExample( Control* sender, int value ) {
switch ( value ) {
void otherSwitchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print( "Active:" );
break;
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print( "Inactive" );
break;
}
Serial.print("Inactive");
break;
}
Serial.print( " " );
Serial.println( sender->id );
Serial.print(" ");
Serial.println(sender->id);
}
void setup( void ) {
Serial.begin( 115200 );
void setup(void)
{
Serial.begin(115200);
#if defined(ESP32)
WiFi.setHostname( hostname );
WiFi.setHostname(hostname);
#else
WiFi.hostname( hostname );
WiFi.hostname(hostname);
#endif
// try to connect to existing network
WiFi.begin( ssid, password );
Serial.print( "\n\nTry to connect to existing network" );
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
{
uint8_t timeout = 10;
{
uint8_t timeout = 10;
// Wait for connection, 5s timeout
do {
delay( 500 );
Serial.print( "." );
timeout--;
} while ( timeout && WiFi.status() != WL_CONNECTED );
// Wait for connection, 5s timeout
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// not connected -> create hotspot
if ( WiFi.status() != WL_CONNECTED ) {
Serial.print( "\n\nCreating hotspot" );
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED)
{
Serial.print("\n\nCreating hotspot");
WiFi.mode( WIFI_AP );
WiFi.softAPConfig( apIP, apIP, IPAddress( 255, 255, 255, 0 ) );
WiFi.softAP( ssid );
WiFi.mode(WIFI_AP);
delay(100);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
#if defined(ESP32)
uint32_t chipid = 0;
for (int i = 0; i < 17; i = i + 8)
{
chipid |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
#else
uint32_t chipid = ESP.getChipId();
#endif
char ap_ssid[25];
snprintf(ap_ssid, 26, "ESPUI-%08X", chipid);
WiFi.softAP(ap_ssid);
timeout = 5;
timeout = 5;
do {
delay( 500 );
Serial.print( "." );
timeout--;
} while ( timeout );
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
}
}
}
dnsServer.start( DNS_PORT, "*", apIP );
dnsServer.start(DNS_PORT, "*", apIP);
Serial.println( "\n\nWiFi parameters:" );
Serial.print( "Mode: " );
Serial.println( WiFi.getMode() == WIFI_AP ? "Station" : "Client" );
Serial.print( "IP address: " );
Serial.println( WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP() );
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
uint16_t tab1 = ESPUI.addControl( ControlType::Tab, "Settings 1", "Settings 1" );
uint16_t tab2 = ESPUI.addControl( ControlType::Tab, "Settings 2", "Settings 2" );
uint16_t tab3 = ESPUI.addControl( ControlType::Tab, "Settings 3", "Settings 3" );
uint16_t tab1 = ESPUI.addControl(ControlType::Tab, "Settings 1", "Settings 1");
uint16_t tab2 = ESPUI.addControl(ControlType::Tab, "Settings 2", "Settings 2");
uint16_t tab3 = ESPUI.addControl(ControlType::Tab, "Settings 3", "Settings 3");
// shown above all tabs
status = ESPUI.addControl( ControlType::Label, "Status:", "Stop", ControlColor::Turquoise );
// shown above all tabs
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
uint16_t select1 = ESPUI.addControl( ControlType::Select, "Select:", "", ControlColor::Alizarin, tab1, &selectExample );
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 );
uint16_t select1
= ESPUI.addControl(ControlType::Select, "Select:", "", ControlColor::Alizarin, tab1, &selectExample);
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);
ESPUI.addControl( ControlType::Text, "Text Test:", "a Text Field", ControlColor::Alizarin, tab1, &textCall );
ESPUI.addControl(ControlType::Text, "Text Test:", "a Text Field", ControlColor::Alizarin, tab1, &textCall);
// tabbed controls
ESPUI.addControl( ControlType::Label, "Millis:", "0", ControlColor::Emerald, tab1 );
button1 = ESPUI.addControl( ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, tab1, &buttonCallback );
ESPUI.addControl( ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, tab1, &buttonExample );
ESPUI.addControl( ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, tab2, &padExample );
ESPUI.addControl( ControlType::Pad, "Pad without center", "", ControlColor::Carrot, tab3, &padExample );
switchOne = ESPUI.addControl( ControlType::Switcher, "Switch one", "", ControlColor::Alizarin, tab3, &switchExample );
ESPUI.addControl( ControlType::Switcher, "Switch two", "", ControlColor::None, tab3, &otherSwitchExample );
ESPUI.addControl( ControlType::Slider, "Slider one", "30", ControlColor::Alizarin, tab1, &slider );
ESPUI.addControl( ControlType::Slider, "Slider two", "100", ControlColor::Alizarin, tab3, &slider );
ESPUI.addControl( ControlType::Number, "Number:", "50", ControlColor::Alizarin, tab3, &numberCall );
// tabbed controls
ESPUI.addControl(ControlType::Label, "Millis:", "0", ControlColor::Emerald, tab1);
button1 = ESPUI.addControl(
ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, tab1, &buttonCallback);
ESPUI.addControl(ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, tab1, &buttonExample);
ESPUI.addControl(ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, tab2, &padExample);
ESPUI.addControl(ControlType::Pad, "Pad without center", "", ControlColor::Carrot, tab3, &padExample);
switchOne = ESPUI.addControl(ControlType::Switcher, "Switch one", "", ControlColor::Alizarin, tab3, &switchExample);
ESPUI.addControl(ControlType::Switcher, "Switch two", "", ControlColor::None, tab3, &otherSwitchExample);
ESPUI.addControl(ControlType::Slider, "Slider one", "30", ControlColor::Alizarin, tab1, &slider);
ESPUI.addControl(ControlType::Slider, "Slider two", "100", ControlColor::Alizarin, tab3, &slider);
ESPUI.addControl(ControlType::Number, "Number:", "50", ControlColor::Alizarin, tab3, &numberCall);
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from SPIFFS use ESPUI.beginSPIFFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from LITTLEFS use ESPUI.beginLITTLEFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
ESPUI.begin("ESPUI Control");
ESPUI.begin("ESPUI Control");
}
void loop( void ) {
dnsServer.processNextRequest();
void loop(void)
{
dnsServer.processNextRequest();
static long oldTime = 0;
static bool switchi = false;
static long oldTime = 0;
static bool switchi = false;
if ( millis() - oldTime > 5000 ) {
switchi = !switchi;
ESPUI.updateControlValue( switchOne, switchi ? "1" : "0" );
if (millis() - oldTime > 5000)
{
switchi = !switchi;
ESPUI.updateControlValue(switchOne, switchi ? "1" : "0");
oldTime = millis();
}
oldTime = millis();
}
}

View File

@ -21,6 +21,7 @@ slider KEYWORD2
begin KEYWORD2
beginSPIFFS KEYWORD2
beginLITTLEFS KEYWORD2
print KEYWORD2
updateSwitcher KEYWORD2
updateSlider KEYWORD2

View File

@ -6,13 +6,16 @@
"type": "git",
"url": "https://github.com/s00500/ESPUI.git"
},
"authors": [{
"name": "Lukas Bachschwell",
"email": "lukas@lbsfilm.at",
"url": "https://lbsfilm.at",
"maintainer": true
}],
"dependencies": [{
"authors": [
{
"name": "Lukas Bachschwell",
"email": "lukas@lbsfilm.at",
"url": "https://lbsfilm.at",
"maintainer": true
}
],
"dependencies": [
{
"name": "ESP Async WebServer",
"authors": "Hristo Gochkov",
"frameworks": "arduino"
@ -21,9 +24,14 @@
"name": "ArduinoJson",
"authors": "Benoit Blanchon",
"frameworks": "arduino"
},
{
"name": "LittleFS_esp32",
"authors": "lorol",
"frameworks": "arduino"
}
],
"version": "2.0.1",
"version": "2.1.0",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -1,5 +1,5 @@
name=ESPUI
version=2.0.1
version=2.1.0
author=Lukas Bachschwell
maintainer=Lukas Bachschwell <lukas@lbsfilm.at>
sentence=ESP32 and ESP8266 Web Interface Library

1
pio_examples/gui/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.pio

View File

@ -0,0 +1,37 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = ./src
data_dir = ../../data
[env]
lib_extra_dirs = ../../
board_build.filesystem = littlefs
; Additional scripts: Usage: see https://github.com/s00500/ESPUI/issues/144#issuecomment-1005135077
;extra_scripts =
; LittleFSBuilder.py
[env:esp8266]
platform = espressif8266
framework = arduino
board = nodemcuv2
lib_deps =
bblanchon/ArduinoJson @ ^6.18.5
me-no-dev/ESP Async WebServer @ ^1.2.3
[env:esp32]
platform = espressif32
framework = arduino
board = esp32dev
lib_deps =
lorol/LittleFS_esp32@^1.0.6
bblanchon/ArduinoJson @ ^6.18.5
me-no-dev/ESP Async WebServer @ ^1.2.3

View File

@ -0,0 +1,283 @@
#include <DNSServer.h>
#include <ESPUI.h>
const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 4, 1);
DNSServer dnsServer;
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
const char* ssid = "ESPUI";
const char* password = "espui";
const char* hostname = "espui";
int statusLabelId;
int graphId;
int millisLabelId;
int testSwitchId;
void numberCall(Control* sender, int type)
{
Serial.println(sender->value);
}
void textCall(Control* sender, int type)
{
Serial.print("Text: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
}
void slider(Control* sender, int type)
{
Serial.print("Slider: ID: ");
Serial.print(sender->id);
Serial.print(", Value: ");
Serial.println(sender->value);
// Like all Control Values in ESPUI slider values are Strings. To use them as int simply do this:
int sliderValueWithOffset = sender->value.toInt() + 100;
Serial.print("SliderValue with offset");
Serial.println(sliderValueWithOffset);
}
void buttonCallback(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Button UP");
break;
}
}
void buttonExample(Control* sender, int type)
{
switch (type)
{
case B_DOWN:
Serial.println("Status: Start");
ESPUI.print(statusLabelId, "Start");
break;
case B_UP:
Serial.println("Status: Stop");
ESPUI.print(statusLabelId, "Stop");
break;
}
}
void padExample(Control* sender, int value)
{
switch (value)
{
case P_LEFT_DOWN:
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
}
Serial.print(" ");
Serial.println(sender->id);
}
void switchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
}
void otherSwitchExample(Control* sender, int value)
{
switch (value)
{
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(sender->id);
}
void setup(void)
{
ESPUI.setVerbosity(Verbosity::VerboseJSON);
Serial.begin(115200);
#if defined(ESP32)
WiFi.setHostname(hostname);
#else
WiFi.hostname(hostname);
#endif
// try to connect to existing network
WiFi.begin(ssid, password);
Serial.print("\n\nTry to connect to existing network");
{
uint8_t timeout = 10;
// Wait for connection, 5s timeout
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout && WiFi.status() != WL_CONNECTED);
// not connected -> create hotspot
if (WiFi.status() != WL_CONNECTED)
{
Serial.print("\n\nCreating hotspot");
WiFi.mode(WIFI_AP);
delay(100);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
#if defined(ESP32)
uint32_t chipid = 0;
for (int i = 0; i < 17; i = i + 8)
{
chipid |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
#else
uint32_t chipid = ESP.getChipId();
#endif
char ap_ssid[25];
snprintf(ap_ssid, 26, "ESPUI-%08X", chipid);
WiFi.softAP(ap_ssid);
timeout = 5;
do
{
delay(500);
Serial.print(".");
timeout--;
} while (timeout);
}
}
dnsServer.start(DNS_PORT, "*", apIP);
Serial.println("\n\nWiFi parameters:");
Serial.print("Mode: ");
Serial.println(WiFi.getMode() == WIFI_AP ? "Station" : "Client");
Serial.print("IP address: ");
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");
ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press");
ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press");
ESPUI.padWithCenter("Pad with center", &padExample, ControlColor::Sunflower);
ESPUI.pad("Pad without center", &padExample, ControlColor::Carrot);
testSwitchId = ESPUI.switcher("Switch one", &switchExample, ControlColor::Alizarin, false);
ESPUI.switcher("Switch two", &otherSwitchExample, ControlColor::None, true);
ESPUI.slider("Slider one", &slider, ControlColor::Alizarin, 30, 0, 30);
ESPUI.slider("Slider two", &slider, ControlColor::None, 100);
ESPUI.text("Text Test:", &textCall, ControlColor::Alizarin, "a Text Field");
ESPUI.number("Numbertest", &numberCall, ControlColor::Alizarin, 5, 0, 10);
graphId = ESPUI.graph("Graph Test", ControlColor::Wetasphalt);
/*
* .begin loads and serves all files from PROGMEM directly.
* If you want to serve the files from LITTLEFS use ESPUI.beginLITTLEFS
* (.prepareFileSystem has to be run in an empty sketch before)
*/
// Enable this option if you want sliders to be continuous (update during move) and not discrete (update on stop)
// ESPUI.sliderContinuous = true;
/*
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
* SECURE way of limiting access.
* Anyone who is able to sniff traffic will be able to intercept your password
* since it is transmitted in cleartext. Just add a string as username and
* password, for example begin("ESPUI Control", "username", "password")
*/
ESPUI.sliderContinuous = true;
ESPUI.begin("ESPUI Control");
}
void loop(void)
{
dnsServer.processNextRequest();
static long oldTime = 0;
static bool testSwitchState = false;
delay(10);
return;
if (millis() - oldTime > 5000)
{
ESPUI.print(millisLabelId, String(millis()));
ESPUI.addGraphPoint(graphId, random(1, 50));
testSwitchState = !testSwitchState;
ESPUI.updateSwitcher(testSwitchId, testSwitchState);
oldTime = millis();
}
}

View File

@ -15,7 +15,7 @@
uint16_t Control::idCounter = 1;
// ################# Spiffs functions
// ################# LITTLEFS functions
#if defined(ESP32)
void listDir(const char* dirname, uint8_t levels)
{
@ -27,12 +27,11 @@ void listDir(const char* dirname, uint8_t levels)
#endif
#if defined(ESP32)
File root = SPIFFS.open(dirname);
File root = LITTLEFS.open(dirname);
#else
File root = LittleFS.open(dirname);
File root = LittleFS.open(dirname);
#endif
if (!root)
{
#if defined(DEBUG_ESPUI)
@ -116,24 +115,24 @@ void listDir(const char* dirname, uint8_t levels)
void ESPUIClass::list()
{
#if defined(ESP32)
if (!SPIFFS.begin())
{
Serial.println(F("SPIFFS Mount Failed"));
return;
}
if (!LITTLEFS.begin())
{
Serial.println(F("LITTLEFS Mount Failed"));
return;
}
#else
if (!LittleFS.begin())
{
Serial.println(F("LittleFS Mount Failed"));
return;
}
if (!LittleFS.begin())
{
Serial.println(F("LittleFS Mount Failed"));
return;
}
#endif
listDir("/", 1);
#if defined(ESP32)
Serial.println(SPIFFS.totalBytes());
Serial.println(SPIFFS.usedBytes());
Serial.println(LITTLEFS.totalBytes());
Serial.println(LITTLEFS.usedBytes());
#else
FSInfo fs_info;
@ -147,10 +146,10 @@ if (!LittleFS.begin())
void deleteFile(const char* path)
{
#if defined(ESP32)
bool exists = SPIFFS.exists(path);
#if defined(ESP32)
bool exists = LITTLEFS.exists(path);
#else
bool exists = LittleFS.exists(path);
bool exists = LittleFS.exists(path);
#endif
if (!exists)
@ -173,12 +172,12 @@ void deleteFile(const char* path)
#endif
#if defined(ESP32)
bool didRemove = SPIFFS.remove(path);
bool didRemove = LITTLEFS.remove(path);
#else
bool didRemove = LittleFS.remove(path);
bool didRemove = LittleFS.remove(path);
#endif
if (didRemove)
{
if (didRemove)
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -207,13 +206,13 @@ void writeFile(const char* path, const char* data)
#endif
#if defined(ESP32)
File file = SPIFFS.open(path, FILE_WRITE);
File file = LITTLEFS.open(path, FILE_WRITE);
#else
File file = LittleFS.open(path, FILE_WRITE);
File file = LittleFS.open(path, FILE_WRITE);
#endif
if (!file)
{
if (!file)
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -270,7 +269,7 @@ void writeFile(const char* path, const char* data)
file.close();
}
// end Spiffs functions
// end LITTLEFS functions
void ESPUIClass::prepareFileSystem()
{
@ -284,14 +283,14 @@ void ESPUIClass::prepareFileSystem()
#endif
#if defined(ESP32)
SPIFFS.format();
LITTLEFS.format();
if (!SPIFFS.begin(true))
if (!LITTLEFS.begin(true))
{
#if defined(DEBUG_ESPUI)
if (this->verbosity)
{
Serial.println(F("SPIFFS Mount Failed"));
Serial.println(F("LITTLEFS Mount Failed"));
}
#endif
@ -302,7 +301,7 @@ void ESPUIClass::prepareFileSystem()
if (this->verbosity)
{
listDir("/", 1);
Serial.println(F("SPIFFS Mount ESP32 Done"));
Serial.println(F("LITTLEFS Mount ESP32 Done"));
}
#endif
@ -313,7 +312,7 @@ void ESPUIClass::prepareFileSystem()
#if defined(DEBUG_ESPUI)
if (this->verbosity)
{
Serial.println(F("SPIFFS Mount ESP8266 Done"));
Serial.println(F("LITTLEFS Mount ESP8266 Done"));
}
#endif
@ -369,9 +368,9 @@ void ESPUIClass::prepareFileSystem()
#endif
#if defined(ESP32)
SPIFFS.end();
LITTLEFS.end();
#else
LittleFS.end();
LittleFS.end();
#endif
}
@ -381,8 +380,7 @@ void onWsEvent(
{
switch (type)
{
case WS_EVT_DISCONNECT:
{
case WS_EVT_DISCONNECT: {
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -393,8 +391,7 @@ void onWsEvent(
break;
}
case WS_EVT_PONG:
{
case WS_EVT_PONG: {
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -405,8 +402,7 @@ void onWsEvent(
break;
}
case WS_EVT_ERROR:
{
case WS_EVT_ERROR: {
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -417,8 +413,7 @@ void onWsEvent(
break;
}
case WS_EVT_CONNECT:
{
case WS_EVT_CONNECT: {
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -438,8 +433,7 @@ void onWsEvent(
}
break;
case WS_EVT_DATA:
{
case WS_EVT_DATA: {
String msg = "";
msg.reserve(len + 1);
@ -596,7 +590,7 @@ void onWsEvent(
uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color,
uint16_t parentControl, void (*callback)(Control*, int))
{
Control* control = new Control(type, label, callback, value, color, parentControl);
Control* control = new Control(type, label, callback, value, color, true, parentControl);
if (this->controls == nullptr)
{
@ -761,7 +755,12 @@ void ESPUIClass::updateControl(Control* control, int clientId)
root["type"] = (int)control->type + ControlType::UpdateOffset;
root["value"] = control->value;
root["id"] = control->id;
root["visible"] = control->visible;
root["color"] = (int)control->color;
if (control->panelStyle != 0)
root["panelStyle"] = control->panelStyle;
if (control->elementStyle != 0)
root["elementStyle"] = control->elementStyle;
serializeJson(document, json);
#if defined(DEBUG_ESPUI)
@ -786,7 +785,7 @@ void ESPUIClass::updateControl(Control* control, int clientId)
// function like this and it's clients array is private
int tryId = 0;
for (int count = 0; count < this->ws->count();)
for (size_t count = 0; count < this->ws->count();)
{
if (this->ws->hasClient(tryId))
{
@ -802,6 +801,26 @@ void ESPUIClass::updateControl(Control* control, int clientId)
}
}
void ESPUIClass::setPanelStyle(uint16_t id, String style, int clientId)
{
Control* control = getControl(id);
if (control)
{
control->panelStyle = style;
updateControl(control, clientId);
}
}
void ESPUIClass::setElementStyle(uint16_t id, String style, int clientId)
{
Control* control = getControl(id);
if (control)
{
control->elementStyle = style;
updateControl(control, clientId);
}
}
void ESPUIClass::updateControl(uint16_t id, int clientId)
{
Control* control = getControl(id);
@ -889,7 +908,7 @@ void ESPUIClass::updateGauge(uint16_t id, int number, int clientId)
updateControlValue(id, String(number), clientId);
}
void ESPUIClass::clearGraph(uint16_t id, int clientId) {}
void ESPUIClass::clearGraph(uint16_t id, int clientId) { }
void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId)
{
@ -924,7 +943,7 @@ void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId)
// function like this and it's clients array is private
int tryId = 0;
for (int count = 0; count < this->ws->count();)
for (size_t count = 0; count < this->ws->count();)
{
if (this->ws->hasClient(tryId))
{
@ -954,7 +973,7 @@ sent as one blob at the beginning. Therefore a new type is used as well
*/
void ESPUIClass::jsonDom(AsyncWebSocketClient* client)
{
String json;
DynamicJsonDocument document(jsonInitialDocumentSize);
document["type"] = (int)UI_INITIAL_GUI;
document["sliderContinuous"] = sliderContinuous;
@ -966,15 +985,55 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient* client)
titleItem["type"] = (int)UI_TITLE;
titleItem["label"] = ui_title;
while (control != nullptr)
while (1)
{
JsonObject item = items.createNestedObject();
control = prepareJSONChunk(client, control, &items);
String json;
serializeJson(document, json);
#if defined(DEBUG_ESPUI)
if (this->verbosity >= Verbosity::VerboseJSON)
{
Serial.println("Sending elements --------->");
Serial.println(json);
}
#endif
if (client != nullptr)
client->text(json);
else
this->ws->textAll(json);
if (control == nullptr)
break;
document.clear();
items.clear();
document["type"] = (int)UI_EXTEND_GUI;
items = document.createNestedArray("controls");
}
}
/* Prepare a chunk of elements as a single JSON string. If the allowed number of elements is greater than the total
number this will represent the entire UI and this function will return null. If a control pointer is returned then the
limit was reached, the currently serialised must be sent, and then processing resumed to send the next chunk. */
Control* ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, Control* control, JsonArray* items)
{
int elementcount = 0;
while (control != nullptr && elementcount < 10)
{
JsonObject item = items->createNestedObject();
item["id"] = String(control->id);
item["type"] = (int)control->type;
item["label"] = control->label;
item["value"] = String(control->value);
item["color"] = (int)control->color;
item["visible"] = (int)control->visible;
if (control->panelStyle != 0)
item["panelStyle"] = String(control->panelStyle);
if (control->elementStyle != 0)
item["elementStyle"] = String(control->elementStyle);
if (control->parentControl != Control::noParent)
{
@ -996,26 +1055,9 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient* client)
}
control = control->next;
elementcount++;
}
// Send as one big bunch
serializeJson(document, json);
#if defined(DEBUG_ESPUI)
if (this->verbosity >= Verbosity::VerboseJSON)
{
Serial.println(json);
}
#endif
if (client != nullptr)
{
client->text(json);
}
else
{
this->ws->textAll(json);
}
return control;
}
void ESPUIClass::jsonReload()
@ -1037,7 +1079,13 @@ void ESPUIClass::jsonReload()
this->ws->textAll(json);
}
void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const char* password)
void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const char* password, uint16_t port)
{
// Backwards compatibility wrapper
beginLITTLEFS(_title, username, password, port);
}
void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const char* password, uint16_t port)
{
ui_title = _title;
this->basicAuthUsername = username;
@ -1052,20 +1100,20 @@ void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const cha
basicAuth = true;
}
server = new AsyncWebServer(80);
server = new AsyncWebServer(port);
ws = new AsyncWebSocket("/ws");
#if defined(ESP32)
bool fsBegin = SPIFFS.begin();
bool fsBegin = LITTLEFS.begin();
#else
bool fsBegin = LittleFS.begin();
bool fsBegin = LittleFS.begin();
#endif
if (!fsBegin)
{
if (!fsBegin)
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("SPIFFS Mount Failed, PLEASE CHECK THE README ON HOW TO "
Serial.println(F("LITTLEFS Mount Failed, PLEASE CHECK THE README ON HOW TO "
"PREPARE YOUR ESP!!!!!!!"));
}
#endif
@ -1081,12 +1129,12 @@ void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const cha
#endif
#if defined(ESP32)
bool indexExists = SPIFFS.exists("/index.htm");
bool indexExists = LITTLEFS.exists("/index.htm");
#else
bool indexExists = LittleFS.exists("/index.htm");
bool indexExists = LittleFS.exists("/index.htm");
#endif
if (!indexExists)
{
if (!indexExists)
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
@ -1108,17 +1156,17 @@ void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const cha
ws->setAuthentication(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword);
}
#if defined(ESP32)
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
server->serveStatic("/", LITTLEFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
#else
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
#endif
}
else
{
}
else
{
#if defined(ESP32)
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
server->serveStatic("/", LITTLEFS, "/").setDefaultFile("index.htm");
#else
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm");
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm");
#endif
}
@ -1129,7 +1177,7 @@ void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const cha
return request->requestAuthentication();
}
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In SPIFFSmode");
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In LITTLEFS mode");
});
server->onNotFound([](AsyncWebServerRequest* request) { request->send(404); });
@ -1144,7 +1192,7 @@ void ESPUIClass::beginSPIFFS(const char* _title, const char* username, const cha
#endif
}
void ESPUIClass::begin(const char* _title, const char* username, const char* password)
void ESPUIClass::begin(const char* _title, const char* username, const char* password, uint16_t port)
{
basicAuthUsername = username;
basicAuthPassword = password;
@ -1160,7 +1208,7 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas
ui_title = _title;
server = new AsyncWebServer(80);
server = new AsyncWebServer(port);
ws = new AsyncWebSocket("/ws");
ws->onEvent(onWsEvent);

View File

@ -11,8 +11,8 @@
#if defined(ESP32)
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <LITTLEFS.h>
#include "SPIFFS.h"
#include "WiFi.h"
#else
@ -24,7 +24,6 @@
#include <ESPAsyncWebServer.h>
#include <Hash.h>
#include <LittleFS.h>
#include <SPIFFSEditor.h>
#define FILE_WRITE "w"
@ -77,11 +76,13 @@ enum ControlType : uint8_t
UpdateAccel,
InitialGui = 200,
Reload = 201
Reload = 201,
ExtendGUI = 210
};
#define UI_INITIAL_GUI ControlType::InitialGui
#define UI_RELOAD ControlType::Reload
#define UI_EXTEND_GUI ControlType::ExtendGUI
#define UI_TITLE ControlType::Title
#define UI_LABEL ControlType::Label
@ -134,18 +135,22 @@ public:
void (*callback)(Control*, int);
String value;
ControlColor color;
bool visible;
uint16_t parentControl;
String panelStyle;
String elementStyle;
Control* next;
static constexpr uint16_t noParent = 0xffff;
Control(ControlType type, const char* label, void (*callback)(Control*, int), const String& value,
ControlColor color, uint16_t parentControl = Control::noParent)
ControlColor color, bool visible = true, uint16_t parentControl = Control::noParent)
: type(type),
label(label),
callback(callback),
value(value),
color(color),
visible(visible),
parentControl(parentControl),
next(nullptr)
{
@ -159,6 +164,7 @@ public:
callback(control.callback),
value(control.value),
color(control.color),
visible(control.visible),
parentControl(control.parentControl),
next(control.next)
{ }
@ -212,14 +218,16 @@ public:
bool sliderContinuous;
void setVerbosity(Verbosity verbosity);
void begin(const char* _title, const char* username = nullptr,
const char* password = nullptr); // Setup server and page in Memorymode
void beginSPIFFS(const char* _title, const char* username = nullptr,
const char* password = nullptr); // Setup server and page in SPIFFSmode
void begin(const char* _title, const char* username = nullptr, const char* password = nullptr,
uint16_t port = 80); // Setup server and page in Memorymode
void beginSPIFFS(const char* _title, const char* username = nullptr, const char* password = nullptr,
uint16_t port = 80); // Setup server and page in LITTLEFS mode (DEPRECATED, use beginLITTLEFS)
void beginLITTLEFS(const char* _title, const char* username = nullptr, const char* password = nullptr,
uint16_t port = 80); // Setup server and page in LITTLEFS mode
void prepareFileSystem(); // Initially preps the filesystem and loads a lot of
// stuff into SPIFFS
void list(); // Lists SPIFFS directory
// stuff into LITTLEFS
void list(); // Lists LITTLEFS directory
uint16_t addControl(ControlType type, const char* label, const String& value = String(""),
ControlColor color = ControlColor::Turquoise, uint16_t parentControl = Control::noParent,
@ -276,6 +284,9 @@ public:
void clearGraph(uint16_t id, int clientId = -1);
void addGraphPoint(uint16_t id, int nValue, int clientId = -1);
void setPanelStyle(uint16_t id, String style, int clientId = -1);
void setElementStyle(uint16_t id, String style, int clientId = -1);
// Variables
const char* ui_title = "ESPUI"; // Store UI Title and Header Name
Control* controls = nullptr;
@ -291,6 +302,8 @@ private:
const char* basicAuthUsername = nullptr;
const char* basicAuthPassword = nullptr;
bool basicAuth = true;
Control* prepareJSONChunk(AsyncWebSocketClient* client, Control* control, JsonArray* items);
};
extern ESPUIClass ESPUI;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long