#include <WiFi.h>
#include <WebServer.h>
// Access Point Details (Open Network)
const char* ssid = "ESP32 Relay Control";
const char* password = "";
// Define Relay Pin (Using GPIO 23 as requested originally)
const int relayPin = 23;
// Global tracking variable (false = OFF, true = ON)
bool relayState = false;
WebServer server(80);
// UI Design (High-Tech, Minimalist)
String getDashboardHTML() {
String html = "<!DOCTYPE html><html><head>";
html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
html += "<title>ESP32 Control</title>";
html += "<style>";
html += "body { background-color: #0b0f19; color: #00f2ff; font-family: sans-serif; text-align: center; padding: 40px 20px; }";
html += ".panel { max-width: 400px; margin: 0 auto; background: #121826; padding: 30px; border-radius: 8px; border: 1px solid #1e293b; box-shadow: 0 4px 20px rgba(0,0,0,0.5); }";
html += "h2 { font-size: 20px; letter-spacing: 1px; margin-bottom: 30px; color: #ffffff; }";
// Status Indicator
html += ".status { font-size: 24px; font-weight: bold; margin-bottom: 40px; padding: 10px; border-radius: 4px; }";
html += ".status-on { color: #00ff87; text-shadow: 0 0 10px rgba(0,255,135,0.3); }";
html += ".status-off { color: #ff0055; text-shadow: 0 0 10px rgba(255,0,85,0.3); }";
// Buttons
html += ".btn { display: block; width: 100%; padding: 15px; margin: 15px 0; font-size: 16px; font-weight: bold; border: none; border-radius: 4px; cursor: pointer; text-transform: uppercase; transition: all 0.2s ease; }";
html += ".btn-on { background: #00ff87; color: #0b0f19; }";
html += ".btn-on:hover { background: #00e074; box-shadow: 0 0 15px rgba(0,255,135,0.4); }";
html += ".btn-off { background: #ff0055; color: #ffffff; }";
html += ".btn-off:hover { background: #e0004c; box-shadow: 0 0 15px rgba(255,0,85,0.4); }";
html += "</style></head><body>";
html += "<div class=\"panel\">";
html += "<h2>ESP32 RELAY CONTROL</h2>";
if (relayState) {
html += "<div class=\"status status-on\">STATUS: ON</div>";
} else {
html += "<div class=\"status status-off\">STATUS: OFF</div>";
}
html += "<button class=\"btn btn-on\" onclick=\"sendCommand('/on')\">Turn ON</button>";
html += "<button class=\"btn btn-off\" onclick=\"sendCommand('/off')\">Turn OFF</button>";
html += "</div>";
html += "<script>";
html += "function sendCommand(path) {";
html += " var xhr = new XMLHttpRequest();";
html += " xhr.open('GET', path, true);";
html += " xhr.onreadystatechange = function() {";
html += " if (xhr.readyState == 4 && xhr.status == 200) { location.reload(); }";
html += " };";
html += " xhr.send();";
html += "}";
html += "</script>";
html += "</body></html>";
return html;
}
// Web Server Handlers
void handleRoot() {
server.send(200, "text/html", getDashboardHTML());
}
void handleOn() {
relayState = true;
// To turn ON an Active-Low relay: Drive the pin strictly LOW
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
server.send(200, "text/plain", "ON");
}
void handleOff() {
relayState = false;
// To turn OFF: Force the pin into INPUT mode.
// This disconnects the ESP32 pin internally, allowing the relay's built-in pull-up to reach its native 5V safely.
pinMode(relayPin, INPUT);
server.send(200, "text/plain", "OFF");
}
void setup() {
Serial.begin(115200);
// Set initial state to safely OFF on system startup
pinMode(relayPin, INPUT);
// Initialize Soft Access Point
WiFi.softAP(ssid, password);
// Map server endpoints
server.on("/", handleRoot);
server.on("/on", handleOn);
server.on("/off", handleOff);
server.begin();
Serial.println("System Initialized Successfully.");
}
void loop() {
server.handleClient();
}