web-interface-esp32

nazarijtipusak080/esp32-web-interface-1/web-interface-esp32

No description
web-interface-esp32
@/web-interface-esp32
INETjesuso/esp32-wifi/esp32-inet
CONNpulse
Establish the connection
TITLEstring
HTML Title
OPstring
Operation to be done on the web server
STYLEstring
HTML code to style the web server
RUNpulse
web-interface-esp32
IP
DONE
B1
B2
B3
B4
INET
CONN
TITLE
OP
STYLE
RUN
B4boolean
B3boolean
B2boolean
B1boolean
DONEpulse
Pulse when get the IP address
IPxod/net/ip-address
IP address for the web server
To use the node in your project you should have the nazarijtipusak080/esp32-web-interface-1 library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.

C++ implementation

#pragma XOD require "https://github.com/me-no-dev/ESPAsyncWebServer"
#pragma XOD require "https://github.com/me-no-dev/AsyncTCP"

#pragma XOD error_raise enable

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);

// --- глобальні прапорці кнопок ---
bool btn1 = false;
bool btn2 = false;
bool btn3 = false;
bool btn4 = false;

// --- текст змінної для відображення на сторінці ---
namespace input {
    String title = "";
    String style = "";
    String operation = "";
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  %TITLE%
  <style>
    button { width:120px; height:50px; font-size:18px; margin:10px; }
    %STYLE%
  </style>
</head>
<body>
  <h2>ESP32 Button Interface</h2>
  <button onclick="press(1)">Button 1</button>
  <button onclick="press(2)">Button 2</button>
  <button onclick="press(3)">Button 3</button>
  <button onclick="press(4)">Button 4</button>
  <hr>
  <b>Last pressed:</b> <span id="operation">%OPERATION%</span>

<script>
function press(num){
  var xhttp = new XMLHttpRequest();
  xhttp.open("GET", "/press?b=" + num, true);
  xhttp.send();
}

setInterval(function(){
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("operation").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/operation", true);
  xhttp.send();
}, 1000);
</script>
</body>
</html>
)rawliteral";

String processor(const String& var) {
  if (var == "TITLE") return input::title;
  if (var == "STYLE") return input::style;
  if (var == "OPERATION") return input::operation;
  return String();
}

node {
    #define WIFI_TIMEOUT_MS 20000

    void evaluate(Context ctx) {
        // --- старт сервера при CONN ---
        if (isInputDirty<input_CONN>(ctx)) {
            // TITLE
            auto tt = getValue<input_TITLE>(ctx);
            char _tt[length(tt) + 1] = {0};
            dump(tt, _tt);
            // build title string
            String ttl = "";
            for (size_t i = 0; i < sizeof(_tt) && _tt[i] != 0; ++i) ttl += _tt[i];
            input::title = "<title>" + ttl + "</title>";

            // STYLE
            auto st = getValue<input_STYLE>(ctx);
            char _st[length(st) + 1] = {0};
            dump(st, _st);
            String sty = "";
            for (size_t i = 0; i < sizeof(_st) && _st[i] != 0; ++i) sty += _st[i];
            input::style = sty;

            // OP initial
            auto op = getValue<input_OP>(ctx);
            char _op[length(op) + 1] = {0};
            dump(op, _op);
            String opp = "";
            for (size_t i = 0; i < sizeof(_op) && _op[i] != 0; ++i) opp += _op[i];
            input::operation = opp;

            // routes
            server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
                request->send_P(200, "text/html", index_html, processor);
            });

            server.on("/operation", HTTP_GET, [](AsyncWebServerRequest *request){
                request->send_P(200, "text/plain", input::operation.c_str());
            });

            server.on("/press", HTTP_GET, [](AsyncWebServerRequest *request){
                if (request->hasParam("b")) {
                    int b = request->getParam("b")->value().toInt();
                    if (b == 1) { btn1 = true; input::operation = "Button 1"; }
                    if (b == 2) { btn2 = true; input::operation = "Button 2"; }
                    if (b == 3) { btn3 = true; input::operation = "Button 3"; }
                    if (b == 4) { btn4 = true; input::operation = "Button 4"; }
                    request->send(200, "text/plain", input::operation.c_str());
                } else {
                    request->send(400, "text/plain", "Missing b parameter");
                }
            });

            server.begin();

            // Видаємо IP (якщо Wi-Fi підключений) і DONE
            if (WiFi.status() == WL_CONNECTED) {
                emitValue<output_IP>(ctx, WiFi.localIP());
            } else {
                // все одно емiтимо локальний IP (0.0.0.0) якщо немає підключення
                emitValue<output_IP>(ctx, WiFi.localIP());
            }
           
        }

        // --- обробка RUN: оновлюємо OP і STYLE зі входів (ручне оновлення) ---
        if (isInputDirty<input_RUN>(ctx)) {
            // OP
            auto op = getValue<input_OP>(ctx);
            char _op[length(op) + 1] = {0};
            dump(op, _op);
            String opp = "";
            for (size_t i = 0; i < sizeof(_op) && _op[i] != 0; ++i) opp += _op[i];
            input::operation = opp;

            // STYLE (оновлюємо стиль при RUN)
            auto st = getValue<input_STYLE>(ctx);
            char _st[length(st) + 1] = {0};
            dump(st, _st);
            String sty = "";
            for (size_t i = 0; i < sizeof(_st) && _st[i] != 0; ++i) sty += _st[i];
            input::style = sty;
        }

        // --- генерування виходів (імпульси при натисканні) ---
        if (btn1) {
            // видати короткий імпульс — тут ми робимо toggle від поточного стану виходу
            emitValue<output_B1>(ctx, !(getValue<output_B1>(ctx)));
            btn1 = false;
        }
        if (btn2) {
            emitValue<output_B2>(ctx, !(getValue<output_B2>(ctx)));
            btn2 = false;
        }
        if (btn3) {
            emitValue<output_B3>(ctx, !(getValue<output_B3>(ctx)));
            btn3 = false;
        }
        if (btn4) {
            emitValue<output_B4>(ctx, !(getValue<output_B4>(ctx)));
            btn4 = false;
        }
         emitValue<output_DONE>(ctx, 1);
    }
}