#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);
// Змінна для збереження останньої команди
String receivedCommand = "";
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
%TITLE%
%STYLE%
</head>
<body>
<h2>ESP32 Command Server</h2>
<p>Введіть команду:</p>
<input id="cmd" placeholder="Команда..." />
<button onclick="sendCmd()">Надіслати</button>
<hr>
<b>Остання команда:</b> <span id="operation">%OPERATION%</span>
<script>
function sendCmd(){
var c = document.getElementById("cmd").value;
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/set?cmd=" + encodeURIComponent(c), 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();
}, 2000);
</script>
</body>
</html>
)rawliteral";
namespace input {
String operation = "";
String style = "";
String title = "";
}
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 {
void evaluate(Context ctx) {
// --- Ініціалізація сервера ---
if (isInputDirty<input_CONN>(ctx)) {
auto tt = getValue<input_TITLE>(ctx);
char _tt[length(tt) + 1] = {0};
dump(tt, _tt);
input::title = String("<title>") + String(_tt) + String("</title>");
auto st = getValue<input_STYLE>(ctx);
char _st[length(st) + 1] = {0};
dump(st, _st);
input::style = String(_st);
auto op = getValue<input_OP>(ctx);
char _op[length(op) + 1] = {0};
dump(op, _op);
input::operation = String(_op);
// --- Маршрути ---
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("/set", HTTP_GET, [](AsyncWebServerRequest *request){
if (request->hasParam("cmd")) {
receivedCommand = request->getParam("cmd")->value();
input::operation = receivedCommand;
request->send(200, "text/plain", "OK");
} else {
request->send(400, "text/plain", "Missing cmd parameter");
}
});
server.begin();
// IP-адреса
emitValue<output_IP>(ctx, WiFi.localIP());
emitValue<output_DONE>(ctx, 1);
}
// --- Зміна OP вручну ---
if (isInputDirty<input_RUN>(ctx)) {
auto op = getValue<input_OP>(ctx);
char _op[length(op) + 1] = {0};
dump(op, _op);
input::operation = String(_op);
}
// --- Якщо прийшла команда ---
if (receivedCommand.length() > 0) {
emitValue<output_CMD>(ctx, receivedCommand.c_str());
receivedCommand = "";
}
}
}