Marrying ESP32 OTA w/ Existing Code Block

I have managed to 'marry' the two together but my issue is that
when I type in my LAN address on the browser webpage it gives me
the OTA section and not the main code webpage data.
Removing "WiFiClient client = server.available();" and using the OTA
"server.handleClient();" is the problem I assume. But not sure how to fix.

192.168.1.148 = "Hi! This is ElegantOTA Demo.
192.168.1.148/ = same as above
192.168.1.148/update = OTA screen for selecting a file
But no client/server data access related to the ESP temp input.

#include <WiFiClient.h>   // for ElegantOTA
#include <WebServer.h>    // for ElegantOTA

#include <ElegantOTA.h>

#include <WiFi.h>
#include <math.h>
#include <OneWireNg.h>
#include <DallasTemperature.h>

#define SENSOR_PIN 33  // GIOP/GPIO33 Pin 8 [physical pin 8; silkscreen 7]
#define ONBOARD_LED 2
OneWire oneWire(SENSOR_PIN);
DallasTemperature DS18B20(&oneWire);

WiFiClient client;
// WiFiServer server(80);        This I removed to prevent a conflict.
WebServer server(80);
boolean lastConnected   = false;
boolean currentLineIsBlank = false;
int status = WL_IDLE_STATUS; 
char wifissid[] = "xxxxxxxxxxx";  
char wifipass[] = "xxxxxxxxx";       

float tempC;          
float tempF;          
int temp_adj = -1.0;  
int shed_temp;

unsigned long ota_progress_millis = 0;

void onOTAStart() {
  // Log when OTA has started
  Serial.println("OTA update started!");
  // <Add your own code here>
}

void onOTAProgress(size_t current, size_t final) {
  // Log every 1 second
  if (millis() - ota_progress_millis > 1000) {
    ota_progress_millis = millis();
    Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
  }
}

void onOTAEnd(bool success) {
  // Log when OTA has finished
  if (success) {
    Serial.println("OTA update finished successfully!");
  } else {
    Serial.println("There was an error during OTA update!");
  }
}
void setup() {
  Serial.begin(115200);
  
pinMode(ONBOARD_LED, OUTPUT);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Attempting to Connect To Local LAN:   ");
    Serial.println(wifissid);
    WiFi.begin(wifissid, wifipass);
    delay(5000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("  Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  server.begin();                  
  Serial.print("WiFi Status:  ");
  Serial.println(WiFi.status());
  Serial.println();
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());

  server.on("/", []() {
    server.send(200, "text/plain", "Hi! This is ElegantOTA Demo.");
  });

  ElegantOTA.begin(&server);  // Start ElegantOTA
  // ElegantOTA callbacks
  ElegantOTA.onStart(onOTAStart);
  ElegantOTA.onProgress(onOTAProgress);
  ElegantOTA.onEnd(onOTAEnd);

  server.begin();
  Serial.println("HTTP server started");
} 
void loop() {
  server.handleClient();
  ElegantOTA.loop();
  digitalWrite(ONBOARD_LED, HIGH);  
  delay(100);
  Serial.println();
  Serial.print("  LED ON....");
  digitalWrite(ONBOARD_LED, LOW);
  delay(1500);
  Serial.println();
  Serial.print("  LED OFF....");

DS18B20.requestTemperatures();       
  tempF = DS18B20.getTempFByIndex(0);  
  shed_temp = tempF + temp_adj;

// WiFiClient client = server.available();   
  server.handleClient();
  if (client) {
    currentLineIsBlank = true;  

    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n')  //     
        {
          client.println();
          client.println();
          client.print(" Shed Temp:  ");
        client.print(shed_temp);
           client.println();
          break;
        }
      }
    }
    delay(2000);            
    client.stop();                                   
    if (!client.connected() && lastConnected)  
    {                                          
      client.stop();
    }
    lastConnected = client.connected();
  }
}

type or paste code here

If you look into this demo-code

you see that there are defined different
server.on()'s

server.on("/", handle_OnConnect);
  server.on("/led1on", handle_led1on);
  server.on("/led1off", handle_led1off);
  server.on("/led2on", handle_led2on);
  server.on("/led2off", handle_led2off);
  server.onNotFound(handle_NotFound);

If you write such code from scratch you have to write yourself all the fundamentals like

void handle_led1on() {
  LED1status = HIGH;
  Serial.println("GPIO4 Status: ON");
  server.send(200, "text/html", SendHTML(true,LED2status)); 
}

.
.
and then write yourself the SendHTML-function

String SendHTML(uint8_t led1stat,uint8_t led2stat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr +=".button-on {background-color: #3498db;}\n";
  ptr +=".button-on:active {background-color: #2980b9;}\n";
  ptr +=".button-off {background-color: #34495e;}\n";
  ptr +=".button-off:active {background-color: #2c3e50;}\n";
  ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>ESP32 Web Server</h1>\n";
  ptr +="<h3>Using Access Point(AP) Mode</h3>\n";
  
   if(led1stat)
  {ptr +="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";}
  else
  {ptr +="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";}

  if(led2stat)
  {ptr +="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";}
  else
  {ptr +="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";}

  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Which means you have to learn HTML in addition to server-handling
If you do this you have full control about all details but it needs to know all the html-details.

This is the reason why I prefer to use a library for the Web-GUI.
Using such a library eliminates the need to learn html for the price that the design is only partially modifiable

for example ESPUI or ESP-Dash

Here is a demo for ESPUI

#include <DNSServer.h>
#include <ESPUI.h>

const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 4, 1);
DNSServer dnsServer;

#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif

const char* ssid = "ESPUI";
const char* password = "espui";
const char* hostname = "espui";

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)
{
    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);
    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();
    }
}

.
.
here is a ESP-Dash-Demo

#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();
  }  
}

If you look through the the two code-examples you see that all the html-stuff is "under the hood"
and managed for you in the background. Displaying data, reacting on button-clicks on the website is done in pure C++

best regards Stefan

That demo does not include the ElegantOTA library. Have you confirmed that the libraries you're recommending are compatible with ElegantOTA?

I gave a quick look to the library's source code and examples. It appears to simply hook into the standard ESP web server structure by specifying callbacks with the server.on() paradigm. You can do the same to handle your custom web page using the same server the ElegantOTA library is using. Note that you're free to grab the server.on("/"...) callback right off the bat since that's only a "Hello World" for the library. Obviously, you should avoid specifying callbacks for the same cases as defined in ElegantOTA.begin() ... see ElegantOTA.cpp.

In the Arduino IDE, see File --> Examples --> WebServer --> HelloServer for a simple example.

I'd recommend switching over to ESPAsyncWebServer.

Finally, you should ditch all the blocking code in your loop() function. In you other post, I already showed you how to avoid blocking when making DS18B20 measurements. Once your web code is restructured, you can also get rid of that delay(2000).

Stefan,

You gave me a big slice of pie to digest. I will get my fork. Lol..
Thanks for those leads... :+1: :+1: :+1:

gfvalvo,

Appreciate your suggestions! I will check those references out and give async
serious consideration.
And I do still remember about the sensor conversions issue. That was just a
quick small sketch I grabbed to attempt an interface. :+1: :+1:

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