Es gibt eine library namens ESP-Dash mit der man sehr einfach interaktive Web-interfaces programmieren kann.
Der Nachteil ist dass man keinen Einfluss auf das Design des erzeugten Webinterfaces hat
weil alle HTML-Sachen intern in der library gemacht werden.
In der kostenlos Version von ESP-Dash kann man die Reihenfolge der Elemente nicht ändern
sie werden in einer bestimmten Reihenfolge auf den Bildschirm geklatscht und das wars
Die Pro-Version zum kaufen ist mit 39 Dollar schon etwas happig aber dann kann man die Reihenfolge der Elemente selbst festlegen.
Am Design kann man immer noch nichts ändern. Es sei denn man kniet sich halt doch in HTML, CSS und zusätzlich in Vue.js rein um nachzuvollziehen wie das dort programmiert ist.
Es ist wie immer: ein Fertig-Produkt oder in dem Fall das "fast-fertig-Produkt" ist eben fertig.
Wenn man sein ganz eigenes Ding machen will dann muss man es halt doch aus kleinen Elementen zusammensetzen. Genauso wie Gartenhaus-Bausatz kaufen oder alle Bretter und Balken einzeln kaufen und zusägen.
Hier ist ein Demo-Code der die onboard-LED blinken lässt.
Man kann mit einem Schieberegler die Blinkfrequenz verändern
und mit einem Button das Blinken ein-/auschalten
#include <Arduino.h>
#if defined(ESP8266)
/* ESP8266 Dependencies */
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h> //
/* on ESP8266 LED is connected to Vdd => HIGH = LED off */
#define LEDStateOff HIGH
#elif defined(ESP32)
/* ESP32 Dependencies */
#include <WiFi.h>
#include <AsyncTCP.h> // https://github.com/me-no-dev/AsyncTCP
#include <ESPAsyncWebServer.h> // https://github.com/me-no-dev/ESPAsyncWebServer
#define LEDStateOff LOW
#endif
#include <AsyncElegantOTA.h> // manual https://randomnerdtutorials.com/esp32-ota-over-the-air-arduino/
// https://github.com/ayushsharma82/AsyncElegantOTA
#include <ESPDash.h> // https://github.com/ayushsharma82/ESP-DASH
const char *ssid = "";
const char *password = "";
unsigned long MyTestTimer = 0; // variables used with millis() MUST be of type unsigned long
const byte OnBoard_LED = 2;
bool DoBlink = true;
unsigned long BlinkFreq = 500;
int Slider2Pos = 5;
AsyncWebServer MyServer(80);
ESPDash MyDashboard(&MyServer);
// Button Card Format - (Dashboard Instance, Card Type, descriptive Text)
Card MyButton(&MyDashboard, BUTTON_CARD, "Blink On / Off");
// Slider Card Format - (Dashboard Instance, Card Type, descriptive Text, Card Symbol(optional), int min, int max)
Card MySlider1(&MyDashboard, SLIDER_CARD, "Blink-Period in Milliseconds", "", 50, 1000);
Card MySlider2(&MyDashboard, SLIDER_CARD, "2ndSlider", "Testtext", 0, 10);
void PrintFileNameDateTime() {
Serial.println("Code running comes from file ");
Serial.println(__FILE__);
Serial.print(" compiled ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.println(__TIME__);
}
boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - expireTime >= TimePeriod )
{
expireTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
void setup(){
Serial.begin(115200);
delay(200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
pinMode(OnBoard_LED, OUTPUT);
digitalWrite(OnBoard_LED, LOW);
Serial.print("Trying to connect to WiFi..");
Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("connected \r\n type this IP-Adress into your browser ");
Serial.println(WiFi.localIP() );
Serial.println("to see the ESP-Dash-Board");
// Attach Button Callback this function gets executed every time the Button is clicked
MyButton.attachCallback([&](bool MyButtonState){
DoBlink = MyButtonState;
Serial.println("Button Triggered: " + String((MyButtonState)?"true":"false"));
MyButton.update(MyButtonState); //Make sure we update our button's value and send update to dashboard */
MyDashboard.sendUpdates();
});
// Attach Slider Callback this function gets executed every time the slider is adjusted to a new value
MySlider1.attachCallback([&](int MySliderValue){
BlinkFreq = MySliderValue;
Serial.println("MySlider1 Triggered: " + String(MySliderValue));
MySlider1.update(MySliderValue); // Make sure we update our slider's value and send update to dashboard */
MyDashboard.sendUpdates();
});
MySlider2.attachCallback([&](int MySliderValue){
Serial.println("slider2 Triggered: " + String(MySliderValue));
Slider2Pos = MySliderValue;
MySlider2.update(MySliderValue);
MyDashboard.sendUpdates();
});
AsyncElegantOTA.begin(&MyServer); // Start ElegantOTA
MyServer.begin(); // Start server
MyButton.update(DoBlink);
MySlider1.update( int(500) );
MyDashboard.sendUpdates();
}
void loop() {
AsyncElegantOTA.loop(); // this line enables the OTA-updating
if (DoBlink) {
BlinkHeartBeatLED(OnBoard_LED,BlinkFreq / 2); // half and half On/Off
}
else {
digitalWrite(OnBoard_LED,LEDStateOff);
}
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
Slider2Pos++;
if (Slider2Pos > 10) {
Slider2Pos = 0;
}
MySlider2.update( int(Slider2Pos) ); // your code can change the sliders value too
MyDashboard.sendUpdates();
}
}
Das webinterface sieht so aus
In dem Demo-Code ist zusätzlich auch gleich noch elegant OTA eingebaut
Das liefert einen Standard Dateisuchen Dialog im Browser über das man ein vorkompiliertes Programm als neue "firmware" drahtlos O)ver T)he A)ir = OTA aufspielen kann

vgs