mirror of
https://github.com/s00500/ESPUI.git
synced 2026-02-05 17:02:41 +00:00
chreate ports of all examples for pio
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
This commit is contained in:
43
pio_examples/completeExample/platformio.ini
Normal file
43
pio_examples/completeExample/platformio.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
; 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]
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
lib_extra_dirs = ../../
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ ^6.18.5
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
https://github.com/bmedici/ESPAsyncWebServer ; Use a fork of the library that has a bugfix for the compile.... https://github.com/esphome/ESPAsyncWebServer/pull/17
|
||||
|
||||
lib_ignore =
|
||||
ESP Async WebServer ; force the use of the esphome version
|
||||
AsyncTCP ; force the use of the esphome version
|
||||
LittleFS_esp32 ; force the use of the ESP32 built into the core version
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.flash_mode = dout
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
me-no-dev/AsyncTCP
|
||||
monitor_speed = 115200
|
||||
544
pio_examples/completeExample/src/completeExample.cpp
Normal file
544
pio_examples/completeExample/src/completeExample.cpp
Normal file
@@ -0,0 +1,544 @@
|
||||
/**
|
||||
* @file completeExample.cpp
|
||||
* @author Ian Gray @iangray1000
|
||||
*
|
||||
* This is an example GUI to show off all of the features of ESPUI.
|
||||
* This can be built using the Arduino IDE, or PlatformIO.
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* If you just want to see examples of the ESPUI code, jump down to the setUpUI() function
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* When this program boots, it will load an SSID and password from the EEPROM.
|
||||
* The SSID is a null-terminated C string stored at EEPROM addresses 0-31
|
||||
* The password is a null-terminated C string stored at EEPROM addresses 32-95.
|
||||
* If these credentials do not work for some reason, the ESP will create an Access
|
||||
* Point wifi with the SSID HOSTNAME (defined below). You can then connect and use
|
||||
* the controls on the "Wifi Credentials" tab to store credentials into the EEPROM.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include <ESPUI.h>
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#else
|
||||
// esp8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#endif
|
||||
|
||||
//Settings
|
||||
#define SLOW_BOOT 0
|
||||
#define HOSTNAME "ESPUITest"
|
||||
#define FORCE_USE_HOTSPOT 0
|
||||
|
||||
|
||||
//Function Prototypes
|
||||
void connectWifi();
|
||||
void setUpUI();
|
||||
void enterWifiDetailsCallback(Control *sender, int type);
|
||||
void textCallback(Control *sender, int type);
|
||||
void generalCallback(Control *sender, int type);
|
||||
void scrambleCallback(Control *sender, int type);
|
||||
void styleCallback(Control *sender, int type);
|
||||
void updateCallback(Control *sender, int type);
|
||||
void getTimeCallback(Control *sender, int type);
|
||||
void graphAddCallback(Control *sender, int type);
|
||||
void graphClearCallback(Control *sender, int type);
|
||||
void randomString(char *buf, int len);
|
||||
void extendedCallback(Control* sender, int type, void* param);
|
||||
|
||||
//UI handles
|
||||
uint16_t wifi_ssid_text, wifi_pass_text;
|
||||
uint16_t mainLabel, mainSwitcher, mainSlider, mainText, mainNumber, mainScrambleButton, mainTime;
|
||||
uint16_t styleButton, styleLabel, styleSwitcher, styleSlider, styleButton2, styleLabel2, styleSlider2;
|
||||
uint16_t graph;
|
||||
volatile bool updates = false;
|
||||
|
||||
|
||||
|
||||
// This is the main function which builds our GUI
|
||||
void setUpUI() {
|
||||
|
||||
//Turn off verbose debugging
|
||||
ESPUI.setVerbosity(Verbosity::Quiet);
|
||||
|
||||
//Make sliders continually report their position as they are being dragged.
|
||||
ESPUI.sliderContinuous = true;
|
||||
|
||||
//This GUI is going to be a tabbed GUI, so we are adding most controls using ESPUI.addControl
|
||||
//which allows us to set a parent control. If we didn't need tabs we could use the simpler add
|
||||
//functions like:
|
||||
// ESPUI.button()
|
||||
// ESPUI.label()
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Basic Controls
|
||||
* This tab contains all the basic ESPUI controls, and shows how to read and update them at runtime.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto maintab = ESPUI.addControl(Tab, "", "Basic controls");
|
||||
|
||||
ESPUI.addControl(Separator, "General controls", "", None, maintab);
|
||||
ESPUI.addControl(Button, "Button", "Button 1", Alizarin, maintab, extendedCallback, (void*)19);
|
||||
mainLabel = ESPUI.addControl(Label, "Label", "Label text", Emerald, maintab, generalCallback);
|
||||
mainSwitcher = ESPUI.addControl(Switcher, "Switcher", "", Sunflower, maintab, generalCallback);
|
||||
|
||||
//Sliders default to being 0 to 100, but if you want different limits you can add a Min and Max control
|
||||
mainSlider = ESPUI.addControl(Slider, "Slider", "200", Turquoise, maintab, generalCallback);
|
||||
ESPUI.addControl(Min, "", "10", None, mainSlider);
|
||||
ESPUI.addControl(Max, "", "400", None, mainSlider);
|
||||
|
||||
//These are the values for the selector's options. (Note that they *must* be declared static
|
||||
//so that the storage is allocated in global memory and not just on the stack of this function.)
|
||||
static String optionValues[] {"Value 1", "Value 2", "Value 3", "Value 4", "Value 5"};
|
||||
auto mainselector = ESPUI.addControl(Select, "Selector", "Selector", Wetasphalt, maintab, generalCallback);
|
||||
for(auto const& v : optionValues) {
|
||||
ESPUI.addControl(Option, v.c_str(), v, None, mainselector);
|
||||
}
|
||||
|
||||
mainText = ESPUI.addControl(Text, "Text Input", "Initial value", Alizarin, maintab, generalCallback);
|
||||
|
||||
//Number inputs also accept Min and Max components, but you should still validate the values.
|
||||
mainNumber = ESPUI.addControl(Number, "Number Input", "42", Emerald, maintab, generalCallback);
|
||||
ESPUI.addControl(Min, "", "10", None, mainNumber);
|
||||
ESPUI.addControl(Max, "", "50", None, mainNumber);
|
||||
|
||||
ESPUI.addControl(Separator, "Updates", "", None, maintab);
|
||||
|
||||
//This button will update all the updatable controls on this tab to random values
|
||||
mainScrambleButton = ESPUI.addControl(Button, "Scramble Values", "Scramble Values", Carrot, maintab, scrambleCallback);
|
||||
ESPUI.addControl(Switcher, "Constant updates", "0", Carrot, maintab, updateCallback);
|
||||
mainTime = ESPUI.addControl(Time, "", "", None, 0, generalCallback);
|
||||
ESPUI.addControl(Button, "Get Time", "Get Time", Carrot, maintab, getTimeCallback);
|
||||
|
||||
ESPUI.addControl(Separator, "Control Pads", "", None, maintab);
|
||||
ESPUI.addControl(Pad, "Normal", "", Peterriver, maintab, generalCallback);
|
||||
ESPUI.addControl(PadWithCenter, "With center", "", Peterriver, maintab, generalCallback);
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Colours
|
||||
* This tab shows all the basic colours
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto colourtab = ESPUI.addControl(Tab, "", "Colours");
|
||||
ESPUI.addControl(Button, "Alizarin", "Alizarin", Alizarin, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Turquoise", "Turquoise", Turquoise, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Emerald", "Emerald", Emerald, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Peterriver", "Peterriver", Peterriver, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Wetasphalt", "Wetasphalt", Wetasphalt, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Sunflower", "Sunflower", Sunflower, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Carrot", "Carrot", Carrot, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Dark", "Dark", Dark, colourtab, generalCallback);
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Styled controls
|
||||
* This tab shows off how inline CSS styles can be applied to elements and panels in order
|
||||
* to customise the look of the UI.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto styletab = ESPUI.addControl(Tab, "", "Styled controls");
|
||||
styleButton = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
|
||||
styleLabel = ESPUI.addControl(Label, "Styled Label", "This is a label", Alizarin, styletab, generalCallback);
|
||||
styleSwitcher = ESPUI.addControl(Switcher, "Styled Switcher", "1", Alizarin, styletab, generalCallback);
|
||||
styleSlider = ESPUI.addControl(Slider, "Styled Slider", "0", Alizarin, styletab, generalCallback);
|
||||
|
||||
//This button will randomise the colours of the above controls to show updating of inline styles
|
||||
ESPUI.addControl(Button, "Randomise Colours", "Randomise Colours", Sunflower, styletab, styleCallback);
|
||||
|
||||
ESPUI.addControl(Separator, "Other styling examples", "", None, styletab);
|
||||
styleButton2 = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
|
||||
ESPUI.setPanelStyle(styleButton2, "background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%); border-bottom: #555;");
|
||||
ESPUI.setElementStyle(styleButton2, "border-radius: 2em; border: 3px solid black; width: 30%; background-color: #8df;");
|
||||
|
||||
styleSlider2 = ESPUI.addControl(Slider, "Styled Slider", "0", Dark, styletab, generalCallback);
|
||||
ESPUI.setElementStyle(styleSlider2, "background: linear-gradient(to right, red, orange, yellow, green, blue);");
|
||||
|
||||
styleLabel2 = ESPUI.addControl(Label, "Styled Label", "This is a label", Dark, styletab, generalCallback);
|
||||
ESPUI.setElementStyle(styleLabel2, "text-shadow: 3px 3px #74b1ff, 6px 6px #c64ad7; font-size: 60px; font-variant-caps: small-caps; background-color: unset; color: #c4f0bb; -webkit-text-stroke: 1px black;");
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Grouped controls
|
||||
* This tab shows how multiple control can be grouped into the same panel through the use of the
|
||||
* parentControl value. This also shows how to add labels to grouped controls, and how to use vertical controls.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto grouptab = ESPUI.addControl(Tab, "", "Grouped controls");
|
||||
|
||||
//The parent of this button is a tab, so it will create a new panel with one control.
|
||||
auto groupbutton = ESPUI.addControl(Button, "Button Group", "Button A", Dark, grouptab, generalCallback);
|
||||
//However the parent of this button is another control, so therefore no new panel is
|
||||
//created and the button is added to the existing panel.
|
||||
ESPUI.addControl(Button, "", "Button B", Alizarin, groupbutton, generalCallback);
|
||||
ESPUI.addControl(Button, "", "Button C", Alizarin, groupbutton, generalCallback);
|
||||
|
||||
|
||||
//Sliders can be grouped as well
|
||||
//To label each slider in the group, we are going add additional labels and give them custom CSS styles
|
||||
//We need this CSS style rule, which will remove the label's background and ensure that it takes up the entire width of the panel
|
||||
String clearLabelStyle = "background-color: unset; width: 100%;";
|
||||
//First we add the main slider to create a panel
|
||||
auto groupsliders = ESPUI.addControl(Slider, "Slider Group", "10", Dark, grouptab, generalCallback);
|
||||
//Then we add a label and set its style to the clearLabelStyle. Here we've just given it the name "A"
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupsliders), clearLabelStyle);
|
||||
//We can now continue to add additional sliders and labels
|
||||
ESPUI.addControl(Slider, "", "20", None, groupsliders, generalCallback);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupsliders), clearLabelStyle);
|
||||
ESPUI.addControl(Slider, "", "30", None, groupsliders, generalCallback);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupsliders), clearLabelStyle);
|
||||
|
||||
//We can also usefully group switchers.
|
||||
auto groupswitcher = ESPUI.addControl(Switcher, "Switcher Group", "0", Dark, grouptab, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "0", Sunflower, groupswitcher, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
|
||||
//To label these switchers we need to first go onto a "new line" below the line of switchers
|
||||
//To do this we add an empty label set to be clear and full width (with our clearLabelStyle)
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, groupswitcher), clearLabelStyle);
|
||||
//We will now need another label style. This one sets its width to the same as a switcher (and turns off the background)
|
||||
String switcherLabelStyle = "width: 60px; margin-left: .3rem; margin-right: .3rem; background-color: unset;";
|
||||
//We can now just add the styled labels.
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, groupswitcher), switcherLabelStyle);
|
||||
|
||||
//You can mix and match different control types, but the results might sometimes
|
||||
//need additional styling to lay out nicely.
|
||||
auto grouplabel = ESPUI.addControl(Label, "Mixed Group", "Main label", Dark, grouptab);
|
||||
auto grouplabel2 = ESPUI.addControl(Label, "", "Secondary label", Emerald, grouplabel);
|
||||
ESPUI.addControl(Button, "", "Button D", Alizarin, grouplabel, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, grouplabel, generalCallback);
|
||||
ESPUI.setElementStyle(grouplabel2, "font-size: x-large; font-family: serif;");
|
||||
|
||||
//Some controls can even support vertical orientation, currently Switchers and Sliders
|
||||
ESPUI.addControl(Separator, "Vertical controls", "", None, grouptab);
|
||||
auto vertgroupswitcher = ESPUI.addControl(Switcher, "Vertical Switcher Group", "0", Dark, grouptab, generalCallback);
|
||||
ESPUI.setVertical(vertgroupswitcher);
|
||||
//On the following lines we wrap the value returned from addControl and send it straight to setVertical
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
//The mechanism for labelling vertical switchers is the same as we used above for horizontal ones
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupswitcher), clearLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupswitcher), switcherLabelStyle);
|
||||
|
||||
auto vertgroupslider = ESPUI.addControl(Slider, "Vertical Slider Group", "15", Dark, grouptab, generalCallback);
|
||||
ESPUI.setVertical(vertgroupslider);
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "25", None, vertgroupslider, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "35", None, vertgroupslider, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "45", None, vertgroupslider, generalCallback));
|
||||
//The mechanism for labelling vertical sliders is the same as we used above for switchers
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupslider), clearLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupslider), switcherLabelStyle);
|
||||
|
||||
//Note that combining vertical and horizontal sliders is going to result in very messy layout!
|
||||
|
||||
/*
|
||||
* Tab: Example UI
|
||||
* An example UI for the documentation
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto exampletab = ESPUI.addControl(Tab, "Example", "Example");
|
||||
ESPUI.addControl(Separator, "Control and Status", "", None, exampletab);
|
||||
ESPUI.addControl(Switcher, "Power", "1", Alizarin, exampletab, generalCallback);
|
||||
ESPUI.addControl(Label, "Status", "System status: OK", Wetasphalt, exampletab, generalCallback);
|
||||
|
||||
ESPUI.addControl(Separator, "Settings", "", None, exampletab);
|
||||
ESPUI.addControl(PadWithCenter, "Attitude Control", "", Dark, exampletab, generalCallback);
|
||||
auto examplegroup1 = ESPUI.addControl(Button, "Activate Features", "Feature A", Carrot, exampletab, generalCallback);
|
||||
ESPUI.addControl(Button, "Activate Features", "Feature B", Carrot, examplegroup1, generalCallback);
|
||||
ESPUI.addControl(Button, "Activate Features", "Feature C", Carrot, examplegroup1, generalCallback);
|
||||
ESPUI.addControl(Slider, "Value control", "45", Peterriver, exampletab, generalCallback);
|
||||
|
||||
/*
|
||||
* Tab: WiFi Credentials
|
||||
* You use this tab to enter the SSID and password of a wifi network to autoconnect to.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto wifitab = ESPUI.addControl(Tab, "", "WiFi Credentials");
|
||||
wifi_ssid_text = ESPUI.addControl(Text, "SSID", "", Alizarin, wifitab, textCallback);
|
||||
//Note that adding a "Max" control to a text control sets the max length
|
||||
ESPUI.addControl(Max, "", "32", None, wifi_ssid_text);
|
||||
wifi_pass_text = ESPUI.addControl(Text, "Password", "", Alizarin, wifitab, textCallback);
|
||||
ESPUI.addControl(Max, "", "64", None, wifi_pass_text);
|
||||
ESPUI.addControl(Button, "Save", "Save", Peterriver, wifitab, enterWifiDetailsCallback);
|
||||
|
||||
|
||||
//Finally, start up the UI.
|
||||
//This should only be called once we are connected to WiFi.
|
||||
ESPUI.begin(HOSTNAME);
|
||||
}
|
||||
|
||||
//This callback generates and applies inline styles to a bunch of controls to change their colour.
|
||||
//The styles created are of the form:
|
||||
// "border-bottom: #999 3px solid; background-color: #aabbcc;"
|
||||
// "background-color: #aabbcc;"
|
||||
void styleCallback(Control *sender, int type) {
|
||||
//Declare space for style strings. These have to be static so that they are always available
|
||||
//to the websocket layer. If we'd not made them static they'd be allocated on the heap and
|
||||
//will be unavailable when we leave this function.
|
||||
static char stylecol1[60], stylecol2[30];
|
||||
if(type == B_UP) {
|
||||
//Generate two random HTML hex colour codes, and print them into CSS style rules
|
||||
sprintf(stylecol1, "border-bottom: #999 3px solid; background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
|
||||
sprintf(stylecol2, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
|
||||
|
||||
//Apply those styles to various elements to show how controls react to styling
|
||||
ESPUI.setPanelStyle(styleButton, stylecol1);
|
||||
ESPUI.setElementStyle(styleButton, stylecol2);
|
||||
ESPUI.setPanelStyle(styleLabel, stylecol1);
|
||||
ESPUI.setElementStyle(styleLabel, stylecol2);
|
||||
ESPUI.setPanelStyle(styleSwitcher, stylecol1);
|
||||
ESPUI.setElementStyle(styleSwitcher, stylecol2);
|
||||
ESPUI.setPanelStyle(styleSlider, stylecol1);
|
||||
ESPUI.setElementStyle(styleSlider, stylecol2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//This callback updates the "values" of a bunch of controls
|
||||
void scrambleCallback(Control *sender, int type) {
|
||||
static char rndString1[10];
|
||||
static char rndString2[20];
|
||||
static bool scText = false;
|
||||
|
||||
if(type == B_UP) { //Button callbacks generate events for both UP and DOWN.
|
||||
//Generate some random text
|
||||
randomString(rndString1, 10);
|
||||
randomString(rndString2, 20);
|
||||
|
||||
//Set the various controls to random value to show how controls can be updated at runtime
|
||||
ESPUI.updateLabel(mainLabel, String(rndString1));
|
||||
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
|
||||
ESPUI.updateSlider(mainSlider, random(10, 400));
|
||||
ESPUI.updateText(mainText, String(rndString2));
|
||||
ESPUI.updateNumber(mainNumber, random(100000));
|
||||
ESPUI.updateButton(mainScrambleButton, scText ? "Scrambled!" : "Scrambled.");
|
||||
scText = !scText;
|
||||
}
|
||||
}
|
||||
|
||||
void updateCallback(Control *sender, int type) {
|
||||
updates = (sender->value.toInt() > 0);
|
||||
}
|
||||
|
||||
void getTimeCallback(Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
ESPUI.updateTime(mainTime);
|
||||
}
|
||||
}
|
||||
|
||||
void graphAddCallback(Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
ESPUI.addGraphPoint(graph, random(1, 50));
|
||||
}
|
||||
}
|
||||
|
||||
void graphClearCallback(Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
ESPUI.clearGraph(graph);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Most elements in this test UI are assigned this generic callback which prints some
|
||||
//basic information. Event types are defined in ESPUI.h
|
||||
void generalCallback(Control *sender, int type) {
|
||||
Serial.print("CB: id(");
|
||||
Serial.print(sender->id);
|
||||
Serial.print(") Type(");
|
||||
Serial.print(type);
|
||||
Serial.print(") '");
|
||||
Serial.print(sender->label);
|
||||
Serial.print("' = ");
|
||||
Serial.println(sender->value);
|
||||
}
|
||||
|
||||
// Most elements in this test UI are assigned this generic callback which prints some
|
||||
// basic information. Event types are defined in ESPUI.h
|
||||
// The extended param can be used to hold a pointer to additional information
|
||||
// or for C++ it can be used to return a this pointer for quick access
|
||||
// using a lambda function
|
||||
void extendedCallback(Control* sender, int type, void* param)
|
||||
{
|
||||
Serial.print("CB: id(");
|
||||
Serial.print(sender->id);
|
||||
Serial.print(") Type(");
|
||||
Serial.print(type);
|
||||
Serial.print(") '");
|
||||
Serial.print(sender->label);
|
||||
Serial.print("' = ");
|
||||
Serial.println(sender->value);
|
||||
Serial.print("param = ");
|
||||
Serial.println((long)param);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
randomSeed(0);
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
if(SLOW_BOOT) delay(5000); //Delay booting to give time to connect a serial monitor
|
||||
connectWifi();
|
||||
#if defined(ESP32)
|
||||
WiFi.setSleep(false); //For the ESP32: turn off sleeping to increase UI responsivness (at the cost of power use)
|
||||
#endif
|
||||
setUpUI();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static long unsigned lastTime = 0;
|
||||
|
||||
//Send periodic updates if switcher is turned on
|
||||
if(updates && millis() > lastTime + 500) {
|
||||
static uint16_t sliderVal = 10;
|
||||
|
||||
//Flick this switcher on and off
|
||||
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
|
||||
sliderVal += 10;
|
||||
if(sliderVal > 400) sliderVal = 10;
|
||||
|
||||
//Sliders, numbers, and labels can all be updated at will
|
||||
ESPUI.updateSlider(mainSlider, sliderVal);
|
||||
ESPUI.updateNumber(mainNumber, random(100000));
|
||||
ESPUI.updateLabel(mainLabel, String(sliderVal));
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
//Simple debug UART interface
|
||||
if(Serial.available()) {
|
||||
switch(Serial.read()) {
|
||||
case 'w': //Print IP details
|
||||
Serial.println(WiFi.localIP());
|
||||
break;
|
||||
case 'W': //Reconnect wifi
|
||||
connectWifi();
|
||||
break;
|
||||
case 'C': //Force a crash (for testing exception decoder)
|
||||
#if !defined(ESP32)
|
||||
((void (*)())0xf00fdead)();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
Serial.print('#');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ESP32)
|
||||
//We don't need to call this explicitly on ESP32 but we do on 8266
|
||||
MDNS.update();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Utilities
|
||||
//
|
||||
//If you are here just to see examples of how to use ESPUI, you can ignore the following functions
|
||||
//------------------------------------------------------------------------------------------------
|
||||
void readStringFromEEPROM(String& buf, int baseaddress, int size) {
|
||||
buf.reserve(size);
|
||||
for (int i = baseaddress; i < baseaddress+size; i++) {
|
||||
char c = EEPROM.read(i);
|
||||
buf += c;
|
||||
if(!c) break;
|
||||
}
|
||||
}
|
||||
|
||||
void connectWifi() {
|
||||
int connect_timeout;
|
||||
|
||||
#if defined(ESP32)
|
||||
WiFi.setHostname(HOSTNAME);
|
||||
#else
|
||||
WiFi.hostname(HOSTNAME);
|
||||
#endif
|
||||
Serial.println("Begin wifi...");
|
||||
|
||||
//Load credentials from EEPROM
|
||||
if(!(FORCE_USE_HOTSPOT)) {
|
||||
yield();
|
||||
EEPROM.begin(100);
|
||||
String stored_ssid, stored_pass;
|
||||
readStringFromEEPROM(stored_ssid, 0, 32);
|
||||
readStringFromEEPROM(stored_pass, 32, 96);
|
||||
EEPROM.end();
|
||||
|
||||
//Try to connect with stored credentials, fire up an access point if they don't work.
|
||||
#if defined(ESP32)
|
||||
WiFi.begin(stored_ssid.c_str(), stored_pass.c_str());
|
||||
#else
|
||||
WiFi.begin(stored_ssid, stored_pass);
|
||||
#endif
|
||||
connect_timeout = 28; //7 seconds
|
||||
while (WiFi.status() != WL_CONNECTED && connect_timeout > 0) {
|
||||
delay(250);
|
||||
Serial.print(".");
|
||||
connect_timeout--;
|
||||
}
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Wifi started");
|
||||
|
||||
if (!MDNS.begin(HOSTNAME)) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
}
|
||||
} else {
|
||||
Serial.println("\nCreating access point...");
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAPConfig(IPAddress(192, 168, 1, 1), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(HOSTNAME);
|
||||
|
||||
connect_timeout = 20;
|
||||
do {
|
||||
delay(250);
|
||||
Serial.print(",");
|
||||
connect_timeout--;
|
||||
} while(connect_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
void enterWifiDetailsCallback(Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
Serial.println("Saving credentials to EPROM...");
|
||||
Serial.println(ESPUI.getControl(wifi_ssid_text)->value);
|
||||
Serial.println(ESPUI.getControl(wifi_pass_text)->value);
|
||||
unsigned int i;
|
||||
EEPROM.begin(100);
|
||||
for(i = 0; i < ESPUI.getControl(wifi_ssid_text)->value.length(); i++) {
|
||||
EEPROM.write(i, ESPUI.getControl(wifi_ssid_text)->value.charAt(i));
|
||||
if(i==30) break; //Even though we provided a max length, user input should never be trusted
|
||||
}
|
||||
EEPROM.write(i, '\0');
|
||||
|
||||
for(i = 0; i < ESPUI.getControl(wifi_pass_text)->value.length(); i++) {
|
||||
EEPROM.write(i + 32, ESPUI.getControl(wifi_pass_text)->value.charAt(i));
|
||||
if(i==94) break; //Even though we provided a max length, user input should never be trusted
|
||||
}
|
||||
EEPROM.write(i + 32, '\0');
|
||||
EEPROM.end();
|
||||
}
|
||||
}
|
||||
|
||||
void textCallback(Control *sender, int type) {
|
||||
//This callback is needed to handle the changed values, even though it doesn't do anything itself.
|
||||
}
|
||||
|
||||
void randomString(char *buf, int len) {
|
||||
for(auto i = 0; i < len-1; i++)
|
||||
buf[i] = random(0, 26) + 'A';
|
||||
buf[len-1] = '\0';
|
||||
}
|
||||
43
pio_examples/completeLambda/platformio.ini
Normal file
43
pio_examples/completeLambda/platformio.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
; 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]
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
lib_extra_dirs = ../../
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ ^6.18.5
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
https://github.com/bmedici/ESPAsyncWebServer ; Use a fork of the library that has a bugfix for the compile.... https://github.com/esphome/ESPAsyncWebServer/pull/17
|
||||
|
||||
lib_ignore =
|
||||
ESP Async WebServer ; force the use of the esphome version
|
||||
AsyncTCP ; force the use of the esphome version
|
||||
LittleFS_esp32 ; force the use of the ESP32 built into the core version
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.flash_mode = dout
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
me-no-dev/AsyncTCP
|
||||
monitor_speed = 115200
|
||||
524
pio_examples/completeLambda/src/completeLambda.cpp
Normal file
524
pio_examples/completeLambda/src/completeLambda.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/**
|
||||
* @file completeLambda.cpp
|
||||
* @author Ian Gray @iangray1000
|
||||
*
|
||||
* This is an example GUI to show off all of the features of ESPUI.
|
||||
* This can be built using the Arduino IDE, or PlatformIO.
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* If you just want to see examples of the ESPUI code, jump down to the setUpUI() function
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* When this program boots, it will load an SSID and password from the EEPROM.
|
||||
* The SSID is a null-terminated C string stored at EEPROM addresses 0-31
|
||||
* The password is a null-terminated C string stored at EEPROM addresses 32-95.
|
||||
* If these credentials do not work for some reason, the ESP will create an Access
|
||||
* Point wifi with the SSID HOSTNAME (defined below). You can then connect and use
|
||||
* the controls on the "Wifi Credentials" tab to store credentials into the EEPROM.
|
||||
*
|
||||
* Version with lambdas. Comparing to version with only callbacks:
|
||||
* diff -u ../completeExample/completeExample.cpp completeLambda.cpp|less
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include <ESPUI.h>
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#else
|
||||
// esp8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#endif
|
||||
|
||||
//Settings
|
||||
#define SLOW_BOOT 0
|
||||
#define HOSTNAME "ESPUITest"
|
||||
#define FORCE_USE_HOTSPOT 0
|
||||
|
||||
|
||||
//Function Prototypes
|
||||
void connectWifi();
|
||||
void setUpUI();
|
||||
void textCallback(Control *sender, int type);
|
||||
void generalCallback(Control *sender, int type);
|
||||
void randomString(char *buf, int len);
|
||||
void paramCallback(Control* sender, int type, int param);
|
||||
|
||||
//UI handles
|
||||
uint16_t wifi_ssid_text, wifi_pass_text;
|
||||
uint16_t mainLabel, mainSwitcher, mainSlider, mainText, mainNumber, mainScrambleButton, mainTime;
|
||||
uint16_t styleButton, styleLabel, styleSwitcher, styleSlider, styleButton2, styleLabel2, styleSlider2;
|
||||
uint16_t graph;
|
||||
volatile bool updates = false;
|
||||
|
||||
|
||||
|
||||
// This is the main function which builds our GUI
|
||||
void setUpUI() {
|
||||
|
||||
//Turn off verbose debugging
|
||||
ESPUI.setVerbosity(Verbosity::Quiet);
|
||||
|
||||
//Make sliders continually report their position as they are being dragged.
|
||||
ESPUI.sliderContinuous = true;
|
||||
|
||||
//This GUI is going to be a tabbed GUI, so we are adding most controls using ESPUI.addControl
|
||||
//which allows us to set a parent control. If we didn't need tabs we could use the simpler add
|
||||
//functions like:
|
||||
// ESPUI.button()
|
||||
// ESPUI.label()
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Basic Controls
|
||||
* This tab contains all the basic ESPUI controls, and shows how to read and update them at runtime.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto maintab = ESPUI.addControl(Tab, "", "Basic controls");
|
||||
|
||||
ESPUI.addControl(Separator, "General controls", "", None, maintab);
|
||||
ESPUI.addControl(Button, "Button", "Button 1", Alizarin, maintab, [](Control *sender, int type){ paramCallback(sender, type, 19); });
|
||||
mainLabel = ESPUI.addControl(Label, "Label", "Label text", Emerald, maintab, generalCallback);
|
||||
mainSwitcher = ESPUI.addControl(Switcher, "Switcher", "", Sunflower, maintab, generalCallback);
|
||||
|
||||
//Sliders default to being 0 to 100, but if you want different limits you can add a Min and Max control
|
||||
mainSlider = ESPUI.addControl(Slider, "Slider", "200", Turquoise, maintab, generalCallback);
|
||||
ESPUI.addControl(Min, "", "10", None, mainSlider);
|
||||
ESPUI.addControl(Max, "", "400", None, mainSlider);
|
||||
|
||||
//These are the values for the selector's options. (Note that they *must* be declared static
|
||||
//so that the storage is allocated in global memory and not just on the stack of this function.)
|
||||
static String optionValues[] {"Value 1", "Value 2", "Value 3", "Value 4", "Value 5"};
|
||||
auto mainselector = ESPUI.addControl(Select, "Selector", "Selector", Wetasphalt, maintab, generalCallback);
|
||||
for(auto const& v : optionValues) {
|
||||
ESPUI.addControl(Option, v.c_str(), v, None, mainselector);
|
||||
}
|
||||
|
||||
mainText = ESPUI.addControl(Text, "Text Input", "Initial value", Alizarin, maintab, generalCallback);
|
||||
|
||||
//Number inputs also accept Min and Max components, but you should still validate the values.
|
||||
mainNumber = ESPUI.addControl(Number, "Number Input", "42", Emerald, maintab, generalCallback);
|
||||
ESPUI.addControl(Min, "", "10", None, mainNumber);
|
||||
ESPUI.addControl(Max, "", "50", None, mainNumber);
|
||||
|
||||
ESPUI.addControl(Separator, "Updates", "", None, maintab);
|
||||
|
||||
//This button will update all the updatable controls on this tab to random values
|
||||
mainScrambleButton = ESPUI.addControl(Button, "Scramble Values", "Scramble Values", Carrot, maintab,
|
||||
//This callback updates the "values" of a bunch of controls
|
||||
[](Control *sender, int type) {
|
||||
static char rndString1[10];
|
||||
static char rndString2[20];
|
||||
static bool scText = false;
|
||||
|
||||
if(type == B_UP) { //Button callbacks generate events for both UP and DOWN.
|
||||
//Generate some random text
|
||||
randomString(rndString1, 10);
|
||||
randomString(rndString2, 20);
|
||||
|
||||
//Set the various controls to random value to show how controls can be updated at runtime
|
||||
ESPUI.updateLabel(mainLabel, String(rndString1));
|
||||
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
|
||||
ESPUI.updateSlider(mainSlider, random(10, 400));
|
||||
ESPUI.updateText(mainText, String(rndString2));
|
||||
ESPUI.updateNumber(mainNumber, random(100000));
|
||||
ESPUI.updateButton(mainScrambleButton, scText ? "Scrambled!" : "Scrambled.");
|
||||
scText = !scText;
|
||||
}
|
||||
});
|
||||
|
||||
ESPUI.addControl(Switcher, "Constant updates", "0", Carrot, maintab,
|
||||
[](Control *sender, int type) {
|
||||
updates = (sender->value.toInt() > 0);
|
||||
});
|
||||
|
||||
mainTime = ESPUI.addControl(Time, "", "", None, 0, generalCallback);
|
||||
|
||||
ESPUI.addControl(Button, "Get Time", "Get Time", Carrot, maintab,
|
||||
[](Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
ESPUI.updateTime(mainTime);
|
||||
}
|
||||
});
|
||||
|
||||
ESPUI.addControl(Separator, "Control Pads", "", None, maintab);
|
||||
ESPUI.addControl(Pad, "Normal", "", Peterriver, maintab, generalCallback);
|
||||
ESPUI.addControl(PadWithCenter, "With center", "", Peterriver, maintab, generalCallback);
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Colours
|
||||
* This tab shows all the basic colours
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto colourtab = ESPUI.addControl(Tab, "", "Colours");
|
||||
ESPUI.addControl(Button, "Alizarin", "Alizarin", Alizarin, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Turquoise", "Turquoise", Turquoise, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Emerald", "Emerald", Emerald, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Peterriver", "Peterriver", Peterriver, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Wetasphalt", "Wetasphalt", Wetasphalt, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Sunflower", "Sunflower", Sunflower, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Carrot", "Carrot", Carrot, colourtab, generalCallback);
|
||||
ESPUI.addControl(Button, "Dark", "Dark", Dark, colourtab, generalCallback);
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Styled controls
|
||||
* This tab shows off how inline CSS styles can be applied to elements and panels in order
|
||||
* to customise the look of the UI.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto styletab = ESPUI.addControl(Tab, "", "Styled controls");
|
||||
styleButton = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
|
||||
styleLabel = ESPUI.addControl(Label, "Styled Label", "This is a label", Alizarin, styletab, generalCallback);
|
||||
styleSwitcher = ESPUI.addControl(Switcher, "Styled Switcher", "1", Alizarin, styletab, generalCallback);
|
||||
styleSlider = ESPUI.addControl(Slider, "Styled Slider", "0", Alizarin, styletab, generalCallback);
|
||||
|
||||
//This button will randomise the colours of the above controls to show updating of inline styles
|
||||
ESPUI.addControl(Button, "Randomise Colours", "Randomise Colours", Sunflower, styletab,
|
||||
//This callback generates and applies inline styles to a bunch of controls to change their colour.
|
||||
//The styles created are of the form:
|
||||
// "border-bottom: #999 3px solid; background-color: #aabbcc;"
|
||||
// "background-color: #aabbcc;"
|
||||
[](Control *sender, int type) {
|
||||
//Declare space for style strings. These have to be static so that they are always available
|
||||
//to the websocket layer. If we'd not made them static they'd be allocated on the heap and
|
||||
//will be unavailable when we leave this function.
|
||||
static char stylecol1[60], stylecol2[30];
|
||||
if(type == B_UP) {
|
||||
//Generate two random HTML hex colour codes, and print them into CSS style rules
|
||||
sprintf(stylecol1, "border-bottom: #999 3px solid; background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
|
||||
sprintf(stylecol2, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
|
||||
|
||||
//Apply those styles to various elements to show how controls react to styling
|
||||
ESPUI.setPanelStyle(styleButton, stylecol1);
|
||||
ESPUI.setElementStyle(styleButton, stylecol2);
|
||||
ESPUI.setPanelStyle(styleLabel, stylecol1);
|
||||
ESPUI.setElementStyle(styleLabel, stylecol2);
|
||||
ESPUI.setPanelStyle(styleSwitcher, stylecol1);
|
||||
ESPUI.setElementStyle(styleSwitcher, stylecol2);
|
||||
ESPUI.setPanelStyle(styleSlider, stylecol1);
|
||||
ESPUI.setElementStyle(styleSlider, stylecol2);
|
||||
}
|
||||
});
|
||||
|
||||
ESPUI.addControl(Separator, "Other styling examples", "", None, styletab);
|
||||
styleButton2 = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
|
||||
ESPUI.setPanelStyle(styleButton2, "background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%); border-bottom: #555;");
|
||||
ESPUI.setElementStyle(styleButton2, "border-radius: 2em; border: 3px solid black; width: 30%; background-color: #8df;");
|
||||
|
||||
styleSlider2 = ESPUI.addControl(Slider, "Styled Slider", "0", Dark, styletab, generalCallback);
|
||||
ESPUI.setElementStyle(styleSlider2, "background: linear-gradient(to right, red, orange, yellow, green, blue);");
|
||||
|
||||
styleLabel2 = ESPUI.addControl(Label, "Styled Label", "This is a label", Dark, styletab, generalCallback);
|
||||
ESPUI.setElementStyle(styleLabel2, "text-shadow: 3px 3px #74b1ff, 6px 6px #c64ad7; font-size: 60px; font-variant-caps: small-caps; background-color: unset; color: #c4f0bb; -webkit-text-stroke: 1px black;");
|
||||
|
||||
|
||||
/*
|
||||
* Tab: Grouped controls
|
||||
* This tab shows how multiple control can be grouped into the same panel through the use of the
|
||||
* parentControl value. This also shows how to add labels to grouped controls, and how to use vertical controls.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto grouptab = ESPUI.addControl(Tab, "", "Grouped controls");
|
||||
|
||||
//The parent of this button is a tab, so it will create a new panel with one control.
|
||||
auto groupbutton = ESPUI.addControl(Button, "Button Group", "Button A", Dark, grouptab, generalCallback);
|
||||
//However the parent of this button is another control, so therefore no new panel is
|
||||
//created and the button is added to the existing panel.
|
||||
ESPUI.addControl(Button, "", "Button B", Alizarin, groupbutton, generalCallback);
|
||||
ESPUI.addControl(Button, "", "Button C", Alizarin, groupbutton, generalCallback);
|
||||
|
||||
|
||||
//Sliders can be grouped as well
|
||||
//To label each slider in the group, we are going add additional labels and give them custom CSS styles
|
||||
//We need this CSS style rule, which will remove the label's background and ensure that it takes up the entire width of the panel
|
||||
String clearLabelStyle = "background-color: unset; width: 100%;";
|
||||
//First we add the main slider to create a panel
|
||||
auto groupsliders = ESPUI.addControl(Slider, "Slider Group", "10", Dark, grouptab, generalCallback);
|
||||
//Then we add a label and set its style to the clearLabelStyle. Here we've just given it the name "A"
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupsliders), clearLabelStyle);
|
||||
//We can now continue to add additional sliders and labels
|
||||
ESPUI.addControl(Slider, "", "20", None, groupsliders, generalCallback);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupsliders), clearLabelStyle);
|
||||
ESPUI.addControl(Slider, "", "30", None, groupsliders, generalCallback);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupsliders), clearLabelStyle);
|
||||
|
||||
//We can also usefully group switchers.
|
||||
auto groupswitcher = ESPUI.addControl(Switcher, "Switcher Group", "0", Dark, grouptab, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "0", Sunflower, groupswitcher, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
|
||||
//To label these switchers we need to first go onto a "new line" below the line of switchers
|
||||
//To do this we add an empty label set to be clear and full width (with our clearLabelStyle)
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, groupswitcher), clearLabelStyle);
|
||||
//We will now need another label style. This one sets its width to the same as a switcher (and turns off the background)
|
||||
String switcherLabelStyle = "width: 60px; margin-left: .3rem; margin-right: .3rem; background-color: unset;";
|
||||
//We can now just add the styled labels.
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, groupswitcher), switcherLabelStyle);
|
||||
|
||||
//You can mix and match different control types, but the results might sometimes
|
||||
//need additional styling to lay out nicely.
|
||||
auto grouplabel = ESPUI.addControl(Label, "Mixed Group", "Main label", Dark, grouptab);
|
||||
auto grouplabel2 = ESPUI.addControl(Label, "", "Secondary label", Emerald, grouplabel);
|
||||
ESPUI.addControl(Button, "", "Button D", Alizarin, grouplabel, generalCallback);
|
||||
ESPUI.addControl(Switcher, "", "1", Sunflower, grouplabel, generalCallback);
|
||||
ESPUI.setElementStyle(grouplabel2, "font-size: x-large; font-family: serif;");
|
||||
|
||||
//Some controls can even support vertical orientation, currently Switchers and Sliders
|
||||
ESPUI.addControl(Separator, "Vertical controls", "", None, grouptab);
|
||||
auto vertgroupswitcher = ESPUI.addControl(Switcher, "Vertical Switcher Group", "0", Dark, grouptab, generalCallback);
|
||||
ESPUI.setVertical(vertgroupswitcher);
|
||||
//On the following lines we wrap the value returned from addControl and send it straight to setVertical
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
|
||||
//The mechanism for labelling vertical switchers is the same as we used above for horizontal ones
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupswitcher), clearLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupswitcher), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupswitcher), switcherLabelStyle);
|
||||
|
||||
auto vertgroupslider = ESPUI.addControl(Slider, "Vertical Slider Group", "15", Dark, grouptab, generalCallback);
|
||||
ESPUI.setVertical(vertgroupslider);
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "25", None, vertgroupslider, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "35", None, vertgroupslider, generalCallback));
|
||||
ESPUI.setVertical(ESPUI.addControl(Slider, "", "45", None, vertgroupslider, generalCallback));
|
||||
//The mechanism for labelling vertical sliders is the same as we used above for switchers
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupslider), clearLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupslider), switcherLabelStyle);
|
||||
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupslider), switcherLabelStyle);
|
||||
|
||||
//Note that combining vertical and horizontal sliders is going to result in very messy layout!
|
||||
|
||||
/*
|
||||
* Tab: Example UI
|
||||
* An example UI for the documentation
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto exampletab = ESPUI.addControl(Tab, "Example", "Example");
|
||||
ESPUI.addControl(Separator, "Control and Status", "", None, exampletab);
|
||||
ESPUI.addControl(Switcher, "Power", "1", Alizarin, exampletab, generalCallback);
|
||||
ESPUI.addControl(Label, "Status", "System status: OK", Wetasphalt, exampletab, generalCallback);
|
||||
|
||||
ESPUI.addControl(Separator, "Settings", "", None, exampletab);
|
||||
ESPUI.addControl(PadWithCenter, "Attitude Control", "", Dark, exampletab, generalCallback);
|
||||
auto examplegroup1 = ESPUI.addControl(Button, "Activate Features", "Feature A", Carrot, exampletab, generalCallback);
|
||||
ESPUI.addControl(Button, "Activate Features", "Feature B", Carrot, examplegroup1, generalCallback);
|
||||
ESPUI.addControl(Button, "Activate Features", "Feature C", Carrot, examplegroup1, generalCallback);
|
||||
ESPUI.addControl(Slider, "Value control", "45", Peterriver, exampletab, generalCallback);
|
||||
|
||||
/*
|
||||
* Tab: WiFi Credentials
|
||||
* You use this tab to enter the SSID and password of a wifi network to autoconnect to.
|
||||
*-----------------------------------------------------------------------------------------------------------*/
|
||||
auto wifitab = ESPUI.addControl(Tab, "", "WiFi Credentials");
|
||||
wifi_ssid_text = ESPUI.addControl(Text, "SSID", "", Alizarin, wifitab, textCallback);
|
||||
//Note that adding a "Max" control to a text control sets the max length
|
||||
ESPUI.addControl(Max, "", "32", None, wifi_ssid_text);
|
||||
wifi_pass_text = ESPUI.addControl(Text, "Password", "", Alizarin, wifitab, textCallback);
|
||||
ESPUI.addControl(Max, "", "64", None, wifi_pass_text);
|
||||
ESPUI.addControl(Button, "Save", "Save", Peterriver, wifitab,
|
||||
[](Control *sender, int type) {
|
||||
if(type == B_UP) {
|
||||
Serial.println("Saving credentials to EPROM...");
|
||||
Serial.println(ESPUI.getControl(wifi_ssid_text)->value);
|
||||
Serial.println(ESPUI.getControl(wifi_pass_text)->value);
|
||||
unsigned int i;
|
||||
EEPROM.begin(100);
|
||||
for(i = 0; i < ESPUI.getControl(wifi_ssid_text)->value.length(); i++) {
|
||||
EEPROM.write(i, ESPUI.getControl(wifi_ssid_text)->value.charAt(i));
|
||||
if(i==30) break; //Even though we provided a max length, user input should never be trusted
|
||||
}
|
||||
EEPROM.write(i, '\0');
|
||||
|
||||
for(i = 0; i < ESPUI.getControl(wifi_pass_text)->value.length(); i++) {
|
||||
EEPROM.write(i + 32, ESPUI.getControl(wifi_pass_text)->value.charAt(i));
|
||||
if(i==94) break; //Even though we provided a max length, user input should never be trusted
|
||||
}
|
||||
EEPROM.write(i + 32, '\0');
|
||||
EEPROM.end();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Finally, start up the UI.
|
||||
//This should only be called once we are connected to WiFi.
|
||||
ESPUI.begin(HOSTNAME);
|
||||
}
|
||||
|
||||
|
||||
//Most elements in this test UI are assigned this generic callback which prints some
|
||||
//basic information. Event types are defined in ESPUI.h
|
||||
void generalCallback(Control *sender, int type) {
|
||||
Serial.print("CB: id(");
|
||||
Serial.print(sender->id);
|
||||
Serial.print(") Type(");
|
||||
Serial.print(type);
|
||||
Serial.print(") '");
|
||||
Serial.print(sender->label);
|
||||
Serial.print("' = ");
|
||||
Serial.println(sender->value);
|
||||
}
|
||||
|
||||
// Most elements in this test UI are assigned this generic callback which prints some
|
||||
// basic information. Event types are defined in ESPUI.h
|
||||
// The extended param can be used to pass additional information
|
||||
void paramCallback(Control* sender, int type, int param)
|
||||
{
|
||||
Serial.print("CB: id(");
|
||||
Serial.print(sender->id);
|
||||
Serial.print(") Type(");
|
||||
Serial.print(type);
|
||||
Serial.print(") '");
|
||||
Serial.print(sender->label);
|
||||
Serial.print("' = ");
|
||||
Serial.println(sender->value);
|
||||
Serial.print("param = ");
|
||||
Serial.println(param);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
randomSeed(0);
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
if(SLOW_BOOT) delay(5000); //Delay booting to give time to connect a serial monitor
|
||||
connectWifi();
|
||||
#if defined(ESP32)
|
||||
WiFi.setSleep(false); //For the ESP32: turn off sleeping to increase UI responsivness (at the cost of power use)
|
||||
#endif
|
||||
setUpUI();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static long unsigned lastTime = 0;
|
||||
|
||||
//Send periodic updates if switcher is turned on
|
||||
if(updates && millis() > lastTime + 500) {
|
||||
static uint16_t sliderVal = 10;
|
||||
|
||||
//Flick this switcher on and off
|
||||
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
|
||||
sliderVal += 10;
|
||||
if(sliderVal > 400) sliderVal = 10;
|
||||
|
||||
//Sliders, numbers, and labels can all be updated at will
|
||||
ESPUI.updateSlider(mainSlider, sliderVal);
|
||||
ESPUI.updateNumber(mainNumber, random(100000));
|
||||
ESPUI.updateLabel(mainLabel, String(sliderVal));
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
//Simple debug UART interface
|
||||
if(Serial.available()) {
|
||||
switch(Serial.read()) {
|
||||
case 'w': //Print IP details
|
||||
Serial.println(WiFi.localIP());
|
||||
break;
|
||||
case 'W': //Reconnect wifi
|
||||
connectWifi();
|
||||
break;
|
||||
case 'C': //Force a crash (for testing exception decoder)
|
||||
#if !defined(ESP32)
|
||||
((void (*)())0xf00fdead)();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
Serial.print('#');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ESP32)
|
||||
//We don't need to call this explicitly on ESP32 but we do on 8266
|
||||
MDNS.update();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Utilities
|
||||
//
|
||||
//If you are here just to see examples of how to use ESPUI, you can ignore the following functions
|
||||
//------------------------------------------------------------------------------------------------
|
||||
void readStringFromEEPROM(String& buf, int baseaddress, int size) {
|
||||
buf.reserve(size);
|
||||
for (int i = baseaddress; i < baseaddress+size; i++) {
|
||||
char c = EEPROM.read(i);
|
||||
buf += c;
|
||||
if(!c) break;
|
||||
}
|
||||
}
|
||||
|
||||
void connectWifi() {
|
||||
int connect_timeout;
|
||||
|
||||
#if defined(ESP32)
|
||||
WiFi.setHostname(HOSTNAME);
|
||||
#else
|
||||
WiFi.hostname(HOSTNAME);
|
||||
#endif
|
||||
Serial.println("Begin wifi...");
|
||||
|
||||
//Load credentials from EEPROM
|
||||
if(!(FORCE_USE_HOTSPOT)) {
|
||||
yield();
|
||||
EEPROM.begin(100);
|
||||
String stored_ssid, stored_pass;
|
||||
readStringFromEEPROM(stored_ssid, 0, 32);
|
||||
readStringFromEEPROM(stored_pass, 32, 96);
|
||||
EEPROM.end();
|
||||
|
||||
//Try to connect with stored credentials, fire up an access point if they don't work.
|
||||
#if defined(ESP32)
|
||||
WiFi.begin(stored_ssid.c_str(), stored_pass.c_str());
|
||||
#else
|
||||
WiFi.begin(stored_ssid, stored_pass);
|
||||
#endif
|
||||
connect_timeout = 28; //7 seconds
|
||||
while (WiFi.status() != WL_CONNECTED && connect_timeout > 0) {
|
||||
delay(250);
|
||||
Serial.print(".");
|
||||
connect_timeout--;
|
||||
}
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Wifi started");
|
||||
|
||||
if (!MDNS.begin(HOSTNAME)) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
}
|
||||
} else {
|
||||
Serial.println("\nCreating access point...");
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAPConfig(IPAddress(192, 168, 1, 1), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(HOSTNAME);
|
||||
|
||||
connect_timeout = 20;
|
||||
do {
|
||||
delay(250);
|
||||
Serial.print(",");
|
||||
connect_timeout--;
|
||||
} while(connect_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void textCallback(Control *sender, int type) {
|
||||
//This callback is needed to handle the changed values, even though it doesn't do anything itself.
|
||||
}
|
||||
|
||||
void randomString(char *buf, int len) {
|
||||
for(auto i = 0; i < len-1; i++)
|
||||
buf[i] = random(0, 26) + 'A';
|
||||
buf[len-1] = '\0';
|
||||
}
|
||||
43
pio_examples/gui-generic-api/platformio.ini
Normal file
43
pio_examples/gui-generic-api/platformio.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
; 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]
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
lib_extra_dirs = ../../
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ ^6.18.5
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
https://github.com/bmedici/ESPAsyncWebServer ; Use a fork of the library that has a bugfix for the compile.... https://github.com/esphome/ESPAsyncWebServer/pull/17
|
||||
|
||||
lib_ignore =
|
||||
ESP Async WebServer ; force the use of the esphome version
|
||||
AsyncTCP ; force the use of the esphome version
|
||||
LittleFS_esp32 ; force the use of the ESP32 built into the core version
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.flash_mode = dout
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
me-no-dev/AsyncTCP
|
||||
monitor_speed = 115200
|
||||
303
pio_examples/gui-generic-api/src/gui-generic-api.cpp
Normal file
303
pio_examples/gui-generic-api/src/gui-generic-api.cpp
Normal file
@@ -0,0 +1,303 @@
|
||||
#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
|
||||
// esp8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
|
||||
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 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 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, void* param)
|
||||
{
|
||||
Serial.print("param: ");
|
||||
Serial.println((long)param);
|
||||
switch (type)
|
||||
{
|
||||
case B_DOWN:
|
||||
Serial.println("Status: Start");
|
||||
ESPUI.updateControlValue(status, "Start");
|
||||
|
||||
ESPUI.getControl(button1)->color = ControlColor::Carrot;
|
||||
ESPUI.updateControl(button1);
|
||||
break;
|
||||
|
||||
case B_UP:
|
||||
Serial.println("Status: Stop");
|
||||
ESPUI.updateControlValue(status, "Stop");
|
||||
|
||||
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;
|
||||
|
||||
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 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;
|
||||
|
||||
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());
|
||||
|
||||
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
|
||||
|
||||
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::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, (void*)19);
|
||||
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 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.begin("ESPUI Control");
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
dnsServer.processNextRequest();
|
||||
|
||||
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");
|
||||
|
||||
oldTime = millis();
|
||||
}
|
||||
}
|
||||
43
pio_examples/prepareFilesystem/platformio.ini
Normal file
43
pio_examples/prepareFilesystem/platformio.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
; 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]
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
lib_extra_dirs = ../../
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ ^6.18.5
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
https://github.com/bmedici/ESPAsyncWebServer ; Use a fork of the library that has a bugfix for the compile.... https://github.com/esphome/ESPAsyncWebServer/pull/17
|
||||
|
||||
lib_ignore =
|
||||
ESP Async WebServer ; force the use of the esphome version
|
||||
AsyncTCP ; force the use of the esphome version
|
||||
LittleFS_esp32 ; force the use of the ESP32 built into the core version
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.flash_mode = dout
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
me-no-dev/AsyncTCP
|
||||
monitor_speed = 115200
|
||||
17
pio_examples/prepareFilesystem/src/prepareFilesystem.cpp
Normal file
17
pio_examples/prepareFilesystem/src/prepareFilesystem.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <Arduino.h>
|
||||
#include <ESPUI.h>
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
ESPUI.setVerbosity(Verbosity::Verbose); //Enable verbose output so you see the files in LittleFS
|
||||
delay(500); //Delay to allow Serial Monitor to start after a reset
|
||||
Serial.println(F("\nPreparing filesystem with ESPUI resources"));
|
||||
ESPUI.prepareFileSystem(); //Copy across current version of ESPUI resources
|
||||
Serial.println(F("Done, files..."));
|
||||
ESPUI.list(); //List all files on LittleFS, for info
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
43
pio_examples/tabbedGui/platformio.ini
Normal file
43
pio_examples/tabbedGui/platformio.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
; 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]
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
lib_extra_dirs = ../../
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ ^6.18.5
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
https://github.com/bmedici/ESPAsyncWebServer ; Use a fork of the library that has a bugfix for the compile.... https://github.com/esphome/ESPAsyncWebServer/pull/17
|
||||
|
||||
lib_ignore =
|
||||
ESP Async WebServer ; force the use of the esphome version
|
||||
AsyncTCP ; force the use of the esphome version
|
||||
LittleFS_esp32 ; force the use of the ESP32 built into the core version
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.flash_mode = dout
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
me-no-dev/AsyncTCP
|
||||
monitor_speed = 115200
|
||||
300
pio_examples/tabbedGui/src/tabbedGui.cpp
Normal file
300
pio_examples/tabbedGui/src/tabbedGui.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#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
|
||||
// esp8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
|
||||
const char* ssid = "ESPUI";
|
||||
const char* password = "espui";
|
||||
const char* hostname = "espui";
|
||||
|
||||
uint16_t button1;
|
||||
uint16_t switchOne;
|
||||
uint16_t status;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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, void* param)
|
||||
{
|
||||
Serial.print("param: ");
|
||||
Serial.println((long)param);
|
||||
switch (type)
|
||||
{
|
||||
case B_DOWN:
|
||||
Serial.println("Status: Start");
|
||||
ESPUI.updateControlValue(status, "Start");
|
||||
|
||||
ESPUI.getControl(button1)->color = ControlColor::Carrot;
|
||||
ESPUI.updateControl(button1);
|
||||
break;
|
||||
|
||||
case B_UP:
|
||||
Serial.println("Status: Stop");
|
||||
ESPUI.updateControlValue(status, "Stop");
|
||||
|
||||
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;
|
||||
|
||||
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 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;
|
||||
|
||||
case S_INACTIVE:
|
||||
Serial.print("Inactive");
|
||||
break;
|
||||
}
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.println(sender->id);
|
||||
}
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
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());
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
// 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, (void*)19);
|
||||
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 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.begin("ESPUI Control");
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
dnsServer.processNextRequest();
|
||||
|
||||
static long oldTime = 0;
|
||||
static bool switchi = false;
|
||||
|
||||
if (millis() - oldTime > 5000)
|
||||
{
|
||||
switchi = !switchi;
|
||||
ESPUI.updateControlValue(switchOne, switchi ? "1" : "0");
|
||||
|
||||
oldTime = millis();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user