ESP uses webserver for local control

Because using cloud services is sometimes unreliable, offline control is important. This article uses webserver to implement local web page control. In this way, there is no need to develop a separate APP, and it can be controlled with a browser. All tests in this article are based on ESP32. 8266 has not been tested. Use USE_8266 control.

The core code is as follows:

html.h

#pragma once

const char *AutoConfigHTML = u8R"esp_html(
    <!DOCTYPE html>
<html>

<head>
    <meta charset="UTF8">
    <title>Smart Console</title>
</head>

<body style="font-size: 30px">

    <style>
        .inputText {
            height: 38px;
            font-size: 30px;
            line-height: 30px;
            padding-left: 15px;
            border-radius: 10px;
            background-color: #dff1f7;
            border: 2;
        }

        .inputText:focus {
            outline: none;
            background-color: #d6e4eb;
        }

        .buttonText {
            height: 38px;
            font-size: 30px;
            line-height: 30px;
            padding-left: 15px;
            border-radius: 10px;
            background-color: #FE5E08;
            border: none;
        }

        .buttonText:focus {
            outline: none;
            background-color: #FE5E08;
        }

        .buttonText:disabled {
            background-color: #c9c7c6;
        }
    </style>

    <center>
        <form>
            <input id="btn_test" type="button" class="buttonText" value="Click me to test" onclick="config(this)"/>
            <br/>
            <label id="recvtxt"/>
        </form>
    </center>
    <script language="javascript">
        function config(sender) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4) {
                    if (xmlhttp.status == 200) {
                        document.getElementById("recvtxt").innerText = "Set successfully";
                    }
                    else {
                        document.getElementById("recvtxt").innerText = "Setup failed";
                        document.getElementById("btnsendconfig").disabled = false;
                    }
                }
            }
            xmlhttp.ontimeout = function () {
                window.location.href = "about:blank";
                window.close();
            }
            xmlhttp.open("GET", "/Ctrl?btn_name=" + sender.id, true);
            xmlhttp.timeout = 5000;
            xmlhttp.send();
            document.getElementById("btnsendconfig").disabled = true;
        }
    </script>
</body>

</html>
)esp_html";

webctrl.h

#include <atomic>
#include <thread>
#include <functional>
#include "html.h"

#ifndef AUTOCFGSSID
#define AUTOCFGSSID "ESP_WIFI"
#endif
#ifndef AUTOCFGPSW
#define AUTOCFGPSW "12345678"
#endif

#ifdef USE_8266
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
using TagWebSERVER = ESP8266WebServer;
#else
#include <WiFi.h>
#include <WebServer.h>
using TagWebSERVER = WebServer;
#endif

using FunWebServerCallback = std::function<bool(const char *)>;

classCWebControl
{

protected:
    void HandleHtmlRoot()
    {
        m_ControlWebServer.send(200, "text/html", AutoConfigHTML);
    }

    void HandleHtmlContrl()
    {
        if (m_WebServerCallback)
        {
            bool bRet=m_WebServerCallback(m_ControlWebServer.arg("btn_name").c_str());
            m_ControlWebServer.send(bRet?200:500, "text/html", m_ControlWebServer.arg("btn_name").c_str());
        }
    }

public:
    CWebControl() : m_bRun(false)
    {
    }

    voidInit()
    {
        WiFi.mode(WIFI_AP_STA); // Dual mode
        WiFi.setAutoReconnect(true);

        IPAddress ip, gateway, subnet;
        ip.fromString("192.168.2.1");
        gateway.fromString("192.168.2.1");
        subnet.fromString("255.255.255.0");
        WiFi.softAPConfig(ip, gateway, subnet);

        WiFi.softAP(AUTOCFGSSID, AUTOCFGPSW);

        m_ControlWebServer.on("/", std::bind( & amp;CWebControl::HandleHtmlRoot, this));
        m_ControlWebServer.on("/Ctrl", HTTP_GET, std::bind( & amp;CWebControl::HandleHtmlContrl, this));
    }

    ~CWebControl()
    {
        Stop();
    }

    void Stop()
    {
        m_bRun = false;
        m_ControlWebServer.close();
        if (m_LoopThread.joinable())
        {
            m_LoopThread.join();
        }
    }

    void SetCallBack(FunWebServerCallback callback)
    {
        m_WebServerCallback = callback;
    }

    void Run()
    {
        Stop();
        m_bRun = true;
        m_ControlWebServer.begin(80);
        m_LoopThread = std::thread(std::bind([ & amp;]
                                             {
            while (m_bRun)
        {
            m_ControlWebServer.handleClient();
        } }));
    }

private:
    std::thread m_LoopThread;
    TagWebSERVER m_ControlWebServer;
    std::atomic_bool m_bRun;
    FunWebServerCallback m_WebServerCallback;
};

The calling method is as follows

// Define the hotspot name and password here. The definition must be in front of #include "webCtrl.h"
//Connect to the following hotspot and access 192.168.2.1 in the browser to open the control page. Of course, the IP address can be changed to what you want in webCtrl.h.
//#define AUTOCFGSSID "ESP_WIFI"
//#define AUTOCFGPSW "12345678"

// If you use 8266 to cancel the downcomment
// #define USE_8266
#include "webCtrl.h"

// What I am using here is ESP32 s3. Of course, the code is also common for other models. Because my board here has an RGB. Use it for testing. Please modify as needed
#ifndef USE_8266
#include "RGB.h"
RGB rgb(1, 48); //Note that the board I bought has 48 pins. Your board may not be
#endif

CWebControl g_WebControl;

bool WebCtrlCallBack(const char *name)
{
    // btn_test needs to modify the HTML corresponding ID here. I use btn_test here. Add buttons can be distinguished based on ID.
    if (strcmp(name, "btn_test") == 0)
    {
#ifndef USE_8266
        static bool trunOn = false;
        rgb.showRGB(trunOn = !trunOn, 0, 255, 100);
#endif
    }
    return true;
}

void setup()
{
    // put your setup code here, to run once:
    g_WebControl.Init();
    g_WebControl.SetCallBack(std::bind(WebCtrlCallBack, std::placeholders::_1));
    g_WebControl.Run();

#ifndef USE_8266
    rgb.begin(50);
#endif
}

void loop()
{
    // put your main code here, to run repeatedly:
}

Engineering code download:

[Free] esp32 uses web pages to implement local control resources-CSDN Library