//
// A simple server implementation showing how to:
// * serve static messages
// * read GET and POST parameters
// * handle missing pages / 404s
//
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);
const uint8_t GREEN_LED = 4;
const uint8_t YELLOW_LED = 2;
const uint8_t BUTTON_BLACK = 14;
const uint8_t BUTTON_WHITE = 12;
bool led1State = false;
bool led2State = false;
bool buttonBlackState = false;
bool buttonWhiteState = false;
typedef struct Led_s{
uint8_t pin;
bool changeFlag;
bool * state;
bool * buttonState;
} Led_t;
Led_t GreenLed = {GREEN_LED, false, &led1State, &buttonBlackState};
Led_t YellowLed = {YELLOW_LED, false, &led2State, &buttonWhiteState};
Led_t *leds[] = {&GreenLed, &YellowLed};
void updateLed(Led_t *led) {
if(led){
if (*(led->buttonState)) // == true
{
led->changeFlag = true;
*(led->buttonState) = false;
}
if(led->changeFlag){
led->changeFlag = false;
*(led->state) = !*(led->state);
digitalWrite(led->pin, *(led->state)); // also verify if the state is not null
}
}
}
void toggleLed(Led_t *led) {
led->changeFlag = true; // will be updated as //! *(led->state) = !*(led->state);
}
// Note: Wokwi uses a special WiFi network called Wokwi-GUEST (no password).
// This virtual network provides internet access to the simulated ESP32.
// To learn more: https://docs.wokwi.com/guides/esp32-wifi#connecting-to-the-wifi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const uint8_t WIFI_CHANNEL = 6; // Speeds up the connection in Wokwi
const char* PARAM_MESSAGE = "message";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
String createHtml() {
String response = R"(
<!DOCTYPE html><html>
<head>
<title>ESP32 Web Server Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html { font-family: sans-serif; text-align: center; }
body { display: inline-flex; flex-direction: column; }
h1 { margin-bottom: 1.2em; }
h2 { margin: 0; }
div { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; grid-auto-flow: column; grid-gap: 1em; }
.btn { background-color: #5B5; border: none; color: #fff; padding: 0.5em 1em;
font-size: 2em; text-decoration: none }
.btn.OFF { background-color: #333; }
</style>
</head>
<body>
<h1>ESP32 Web Server</h1>
<div>
<h2>LED 1</h2>
<a href="?toggle=1" class="btn LED1_TEXT">LED1_TEXT</a>
<h2>LED 2</h2>
<a href="?toggle=2" class="btn LED2_TEXT">LED2_TEXT</a>
</div>
</body>
</html>
)";
response.replace("LED1_TEXT", led1State ? "ON" : "OFF");
response.replace("LED2_TEXT", led2State ? "ON" : "OFF");
return response;
}
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Starting ESP32");
pinMode(BUTTON_BLACK, INPUT);
pinMode(BUTTON_WHITE, INPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
Serial.print("Connecting to WiFi... ");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password, WIFI_CHANNEL);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.println(" Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if(request->hasParam("toggle")) {
const AsyncWebParameter* led = request->getParam("toggle");
Serial.print("Toggle LED #");
Serial.println(led->value());
// simple way :
switch (led->value().toInt()) {
case 1:
leds[0]->changeFlag = true; // updating the first LED's changeFlag
break;
case 2:
leds[1]->changeFlag = true; // updating the second LED's changeFlag
break;
}
// more complex way :
// if(led->value().toInt())
// {
// toggleLed(leds[led->value().toInt() - 1]);
// }
}
request->send(200, "text/html", createHtml());
});
// Send a GET request to <IP>/get?message=<message>
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
String message;
if (request->hasParam(PARAM_MESSAGE)) {
message = request->getParam(PARAM_MESSAGE)->value();
} else {
message = "No message sent";
}
request->send(200, "text/plain", "Hello, GET: " + message);
});
// Send a POST request to <IP>/post with a form field message set to <message>
server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
String message;
if (request->hasParam(PARAM_MESSAGE, true)) {
message = request->getParam(PARAM_MESSAGE, true)->value();
} else {
message = "No message sent";
}
request->send(200, "text/plain", "Hello, POST: " + message);
});
server.onNotFound(notFound);
server.begin();
Serial.println("HTTP server started (http://localhost:8180)");
// ATTACH INTERRUPTS TO BUTTONS
attachInterrupt(digitalPinToInterrupt(BUTTON_BLACK), [](){
buttonBlackState = !buttonBlackState;
}, FALLING);
attachInterrupt(digitalPinToInterrupt(BUTTON_WHITE), [](){
buttonWhiteState = !buttonWhiteState;
}, FALLING);
}
void loop() {
// server.handleClient(); // regular web server
for (Led_t *led : leds) {
updateLed(led);
}
}
// #include <Arduino.h>
// #include "pins.h"
// #include "wifi_custom.h"
// void setup()
// {
// Serial.begin(115200);
// pinMode(BUTTON_BLACK, INPUT);
// pinMode(BUTTON_WHITE, INPUT);
// // put your setup code here, to run once:
// pinMode(GREEN_LED, OUTPUT);
// digitalWrite(GREEN_LED, LOW);
// pinMode(YELLOW_LED,OUTPUT);
// digitalWrite(YELLOW_LED, LOW);
// pinMode(RED_LED, OUTPUT);
// digitalWrite(RED_LED, LOW);
// setupServerWiFi();
// }
// void clickHandler()
// {
// // read the state of the switch into a local variable:
// uint8_t reading = digitalRead(buttonPin);
// // check to see if you just pressed the button
// // (i.e. the input went from LOW to HIGH), and you've waited long enough
// // since the last press to ignore any noise:
// // If the switch changed, due to noise or pressing:
// if (reading != lastButtonState) {
// // reset the debouncing timer
// lastDebounceTime = millis();
// }
// if ((millis() - lastDebounceTime) > debounceDelay) {
// // whatever the reading is at, it's been there for longer than the debounce
// // delay, so take it as the actual current state:
// // if the button state has changed:
// if (reading != buttonState) {
// buttonState = reading;
// // only toggle the LED if the new button state is HIGH
// if (buttonState ){// == HIGH) {
// ledState = !ledState;
// //todo for 3 leds
// }
// }
// }
// // set the LED:
// digitalWrite(output, ledState);
// // save the reading. Next time through the loop, it'll be the lastButtonState:
// lastButtonState = reading;
// //easy and bad way
// if (digitalRead(BUTTON_WHITE) == HIGH)
// {
// digitalWrite(GREEN_LED, HIGH);
// delay(ON_DELAY_TIMER);
// digitalWrite(GREEN_LED, LOW);
// delay(OFF_DELAY_TIMER);
// digitalWrite(YELLOW_LED, HIGH);
// delay(ON_DELAY_TIMER);
// digitalWrite(YELLOW_LED, LOW);
// delay(OFF_DELAY_TIMER);
// digitalWrite(RED_LED, HIGH);
// delay(ON_DELAY_TIMER);
// digitalWrite(RED_LED, LOW);
// delay(OFF_DELAY_TIMER);
// }
// }
// void loop()
// {
// clickHandler();
// server.handleClient();
// }