# ESP8266 / ESP32 control IoT with the ESPUI-library Webinterface without HTML-coding

**URL:** <https://forum.arduino.cc/t/esp8266-esp32-control-iot-with-the-espui-library-webinterface-without-html-coding/1046165>\
**Category:** Tutorials\
**Created:** [October 26, 2022, 11:15am UTC](https://forum.arduino.cc/t/esp8266-esp32-control-iot-with-the-espui-library-webinterface-without-html-coding/1046165 "2022-10-26T11:15:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![StefanL38](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/stefanl38/32/713548_2.png) [@StefanL38](https://forum.arduino.cc/u/StefanL38)\
**Post date:** [October 26, 2022, 11:15am UTC](https://forum.arduino.cc/t/esp8266-esp32-control-iot-with-the-espui-library-webinterface-without-html-coding/1046165/1 "2022-10-26T11:15:58Z")

</div>

Hi everybody,

some days ago I started learning the ESPUI-library which can be downloaded here

> **[GitHub - s00500/ESPUI: A simple web user interface library for ESP32 and ESP8266](https://github.com/s00500/ESPUI)**
>
> A simple web user interface library for ESP32 and ESP8266 - GitHub - s00500/ESPUI: A simple web user interface library for ESP32 and ESP8266

No html-knowledge required.  
ESPUI allows to create webinterfaces with a lot of different elements like buttons, switches, sliders etc.  
All this is done through pure C++-function calls. You need to no nothing about html

The documentation in the

> <https://github.com/s00500/ESPUI/blob/master/README.md>

explains the most important basics.  
The examples show different options but are IMHO somehow too much at once  
for explaining how it works in detail

Here is a code that combines the preferences-library with ESPUI.  
compared to the examples that are comming with the library I changed a lot of variable-names to be more self-explaining.  
here is a demo-code that shows how to use tabs  
and how to place UI-elements on the tabs.  
UI-elements on tabs must be created and accessed **different** than on non-tabbed wesites

I added my own standard-functions for debugging and connecting to WiFi

This demo-code uses the library MobaTools for controlling a RC-Servo  
There are two tabs "Operation" and "Settings"  
Tab Operation shows three buttons and a status-text  
Tab Settings shows three number-input-fields with Min/Max-values  
a button for saving the values into flash and a "set default values" button

I hope this help clarifying some details how to use the ESPUI-library.

If you post your codes just do so

```cpp
  #define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " " #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " " #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);

#include <Preferences.h> // add sourcecode file
Preferences myPrefInstance; // create an instance of the object

#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

#include <MobaTools.h>

const byte servoPin = 14; // GPIO 14 is labeled D5
const byte Speed = 230;

MoToServo myServo;
#define ServoMin "700"
#define ServoMax "2300"

unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
unsigned long SwitchStateTimer = 0;

const char *home_ssid = "FRITZ!Box 7490";
const char *home_password = "";

char ap_ssid[25];
const char* AP_password = "espui";
const char* AP_hostname = "espui";

uint16_t myTab1_ID;
uint16_t myTab2_ID;

uint16_t statusLabel_ID;

uint16_t button1_ID;
uint16_t button2_ID;
uint16_t button3_ID;

uint16_t ServoPos1_ID;
uint16_t ServoPos2_ID;
uint16_t ServoPos3_ID;
uint16_t buttonSave_ID;
uint16_t buttonSetDefault_ID;

#define myNameSpace "ServoPos"
const boolean ReadOnly = true;
const boolean ReadWrite = !ReadOnly; // not-operator inverts the value

int servoPos1microS;
int servoPos2microS;
int servoPos3microS;

void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F( __FILE__ ) );
  Serial.print( F(" compiled ") );
  Serial.print( F( __DATE__ ) );
  Serial.print( F(" ") );
  Serial.println( F( __TIME__ ) );
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false; // actual TimePeriod is NOT yet over
}

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 number1Callback(Control* sender, int eventType) {
  Serial.print(" ");
  Serial.print(sender->label);

  Serial.println(sender->value);
  servoPos1microS = atoi(sender->value.c_str());
  dbg("Pos1", servoPos1microS);
}

void number2Callback(Control* sender, int eventType) {
  Serial.print(" ");
  Serial.print(sender->label);

  Serial.println(sender->value);
  servoPos2microS = atoi(sender->value.c_str());
  dbg("Pos2", servoPos2microS);
}

void number3Callback(Control* sender, int eventType) {
  Serial.print(" ");
  Serial.print(sender->label);

  Serial.println(sender->value);
  servoPos3microS = atoi(sender->value.c_str());
  dbg("Pos3", servoPos3microS);
}

void buttonSetDefaultCallback(Control* sender, int eventType) {
  Serial.print("ID: ");
  Serial.print(sender->id);
  Serial.print(" ");
  Serial.println(sender->label);

  if (eventType == B_UP) {
    servoPos1microS = 1100;
    servoPos2microS = 1500;
    servoPos3microS = 1900;
    ESPUI.updateControlValue(ServoPos1_ID, String(servoPos1microS) );
    ESPUI.updateControlValue(ServoPos2_ID, String(servoPos2microS) );
    ESPUI.updateControlValue(ServoPos3_ID, String(servoPos3microS) );

    dbg("Default", servoPos1microS);
    dbg("Default", servoPos2microS);
    dbg("Default", servoPos3microS);
    ESPUI.updateControlValue(statusLabel_ID, "Set positions to default");
  }
}

void buttonSaveCallback(Control* sender, int eventType) {
  Serial.print("ID: ");
  Serial.print(sender->id);
  Serial.print(" ");
  Serial.println(sender->label);
  if (eventType == B_UP) {
    SafePreferences();
    ESPUI.updateControlValue(statusLabel_ID, "positions saved to flash");
  }
}

void button123Callback(Control* sender, int eventType) {

  uint16_t UI_ID = sender->id;

  switch (eventType) {

    case B_DOWN:
      //Serial.println("Button DOWN");
      break;

    case B_UP:
      Serial.print("Button UP ");
      Serial.print("label ");
      Serial.print(sender->label);
      dbg(" Btn123", UI_ID);

      if (UI_ID == button1_ID) {
        myServo.write(servoPos1microS);
        ESPUI.updateControlValue(statusLabel_ID, "Position 1 clicked");
      }
      
      if (UI_ID == button2_ID) {
        myServo.write(servoPos2microS);
        ESPUI.updateControlValue(statusLabel_ID, "Position 2 clicked");
      }

      if (UI_ID == button3_ID) {
        myServo.write(servoPos3microS);
        ESPUI.updateControlValue(statusLabel_ID, "Position 3 clicked");
      }
      break;
  }
}

void ConnectToWiFi() {
  int myCount = 0;
#if defined(ESP32)
  WiFi.setHostname(AP_hostname); // xxy
#else
  WiFi.hostname(AP_hostname);
#endif

  // try to connect to existing network
  WiFi.begin(home_ssid, home_password);
  Serial.print("\n\nTry to connect to existing network");
  Serial.print(" named #");
  Serial.print(home_ssid);
  Serial.println("#");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED && myCount < 31) {
    yield(); // very important to execute yield to make it work
    BlinkHeartBeatLED(OnBoard_LED, 50); // blink LED fast during attempt to connect

    if ( TimePeriodIsOver(MyTestTimer, 500) ) { // once every 500 miliseconds
      Serial.print("."); // print a dot
      myCount++;

      if (myCount > 30) { // after 30 dots = 15 seconds restart
        Serial.println();
        Serial.print("not connected ");
      }
    }
  }

  if (WiFi.status() == WL_CONNECTED ) {
    Serial.println("");
    Serial.print("Connected to #");
    Serial.print(home_ssid);
    Serial.print("# IP address: ");
    Serial.println(WiFi.localIP());
  }
}

void createOwnAP() {
  // not connected -> create hotspot
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("\n\n no connection to SSID #");
    Serial.print(home_ssid);
    Serial.println("#\n Creating 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
    snprintf(ap_ssid, 26, "ESPUI-%08X", chipid);
    WiFi.softAP(ap_ssid);
    Serial.print("SSID #");
    Serial.print(ap_ssid);
    Serial.println("#");

    //dnsServer.start(DNS_PORT, "*", apIP);
  }
}

void printWiFiModeAndIP() {
  if (WiFi.getMode() == WIFI_AP) {
    Serial.print("ESP is its OWN accesspoint with SSID ");
    Serial.println(ap_ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.softAPIP() );
  }
  else {
    Serial.print("ESP connected to existing WLAN named ");
    Serial.println(home_ssid);
    Serial.print("IPAdress: ");
    Serial.println(WiFi.localIP() );
  }
}

void setup() {
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  PrintFileNameDateTime();

#if defined(ESP32)
  WiFi.setHostname(AP_hostname);
#else
  WiFi.hostname(AP_hostname);
#endif

  ConnectToWiFi();
  if (WiFi.status() != WL_CONNECTED) {
    createOwnAP();
  }
  dnsServer.start(DNS_PORT, "*", apIP);
  printWiFiModeAndIP();

  defineUI();
  ESPUI.begin("I am the website created by the ESPUI-Demo");
  LoadPreferences();
  setupServo();
}

void loop() {
  BlinkHeartBeatLED(OnBoard_LED, 500);
  dnsServer.processNextRequest();

  if ( TimePeriodIsOver(MyTestTimer, 1000) ) {
  }

  if ( TimePeriodIsOver(SwitchStateTimer, 5000) ) {
  }
}

void defineUI() {
  // defining the website-tabs
  myTab1_ID = ESPUI.addControl(ControlType::Tab, "Operation", "Operation");
  myTab2_ID = ESPUI.addControl(ControlType::Tab, "Settings", "Settings");

  // shown above all tabs
  statusLabel_ID = ESPUI.addControl(ControlType::Label, "last action:", "Last Action: none", ControlColor::Turquoise);

  // elements on myTab1_ID
  button1_ID = ESPUI.addControl(ControlType::Button, "Position 1", "Pos 1", ControlColor::Peterriver, myTab1_ID, &button123Callback);
  button2_ID = ESPUI.addControl(ControlType::Button, "Position 2", "Pos 2", ControlColor::Wetasphalt, myTab1_ID, &button123Callback);
  button3_ID = ESPUI.addControl(ControlType::Button, "Position 3", "Pos 3", ControlColor::Wetasphalt, myTab1_ID, &button123Callback);

  // elements on myTab2_ID
  ServoPos1_ID = ESPUI.addControl(ControlType::Number, "Servo position 1 (µseconds):", "1100", ControlColor::Alizarin, myTab2_ID, &number1Callback);
  ESPUI.addControl(ControlType::Min, "Min-value", ServoMin, ControlColor::None, ServoPos1_ID);
  ESPUI.addControl(ControlType::Max, "Max-value", ServoMax, ControlColor::None, ServoPos1_ID);

  ServoPos2_ID = ESPUI.addControl(ControlType::Number, "Servo position 2 (µseconds):", "1500", ControlColor::Alizarin, myTab2_ID, &number2Callback);
  ESPUI.addControl(ControlType::Min, "Min-value", ServoMin, ControlColor::None, ServoPos2_ID);
  ESPUI.addControl(ControlType::Max, "Max-value", ServoMax, ControlColor::None, ServoPos2_ID);

  ServoPos3_ID = ESPUI.addControl(ControlType::Number, "Servo position 3 (µseconds):", "1900", ControlColor::Alizarin, myTab2_ID, &number3Callback);
  ESPUI.addControl(ControlType::Min, "Min-value", ServoMin, ControlColor::None, ServoPos3_ID);
  ESPUI.addControl(ControlType::Max, "Max-value", ServoMax, ControlColor::None, ServoPos3_ID);

  buttonSave_ID = ESPUI.addControl(ControlType::Button, "Save to Flash ", "Save ", ControlColor::Peterriver, myTab2_ID, &buttonSaveCallback);
  buttonSetDefault_ID = ESPUI.addControl(ControlType::Button, "Set Default ", "Default ", ControlColor::Peterriver, myTab2_ID, &buttonSetDefaultCallback);
}

void LoadPreferences() {
  Serial.println("LoadPreferences");
  myPrefInstance.begin(myNameSpace, ReadOnly);

  servoPos1microS = myPrefInstance.getInt ("ServoPos1" , 1101);
  servoPos2microS = myPrefInstance.getInt ("ServoPos2" , 1501);
  servoPos3microS = myPrefInstance.getInt ("ServoPos3" , 1901);

  ESPUI.updateControlValue(ServoPos1_ID, String(servoPos1microS) );
  ESPUI.updateControlValue(ServoPos2_ID, String(servoPos2microS) );
  ESPUI.updateControlValue(ServoPos3_ID, String(servoPos3microS) );

  dbg("LP", servoPos1microS);
  dbg("LP", servoPos2microS);
  dbg("LP", servoPos3microS);
  myPrefInstance.end();
}

void SafePreferences() {
  Serial.println("SafePreferences");

  myPrefInstance.begin(myNameSpace, ReadWrite);
  //myPrefInstance.clear();

  myPrefInstance.putInt ("ServoPos1" , servoPos1microS);
  myPrefInstance.putInt ("ServoPos2" , servoPos2microS);
  myPrefInstance.putInt ("ServoPos3" , servoPos3microS);
  myPrefInstance.end();
  dbg("SP", servoPos1microS);
  dbg("SP", servoPos2microS);
  dbg("SP", servoPos3microS);
  LoadPreferences();
}

void setupServo() {
  myServo.attach(servoPin);
  myServo.setMinimumPulse(700);
  myServo.setMaximumPulse(2300);
  myServo.setSpeed(Speed);
  myServo.write(servoPos2microS);
}

```

---

<div class="post-metadata">

**Author:** ![agmue](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/agmue/32/750067_2.png) [@agmue](https://forum.arduino.cc/u/agmue)\
**Post date:** [October 26, 2022, 11:28am UTC](https://forum.arduino.cc/t/esp8266-esp32-control-iot-with-the-espui-library-webinterface-without-html-coding/1046165/2 "2022-10-26T11:28:54Z")

</div>

> [@StefanL38](#):
>
> The documentation in the [read.me](http://read.me) explains the most important basics.

~~Link is defect.~~

 

~~"biut" → "but"~~

solved 🙂

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [April 24, 2023, 11:29am UTC](https://forum.arduino.cc/t/esp8266-esp32-control-iot-with-the-espui-library-webinterface-without-html-coding/1046165/3 "2023-04-24T11:29:07Z")

</div>

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
