/* * ============================================================================= * Fab Academy 2026 — Week 15 — Yaroslav Artsishevskiy * Web button → LED, all on one ESP32-C3 * ----------------------------------------------------------------------------- * This is my Week 11 UDP receiver with a small web server added. * * How it works: * 1. The ESP32 makes its own Wi-Fi network "YaroUDP" (same as Week 11). * 2. I connect my laptop or phone to that network. * 3. I open http://192.168.4.1 in any browser. * 4. The board serves a tiny HTML page with one button. * 5. Clicking the button asks the board to toggle its LED. * * The Week 11 UDP listener is still here too — left as-is, so the same * board can also receive UDP packets from another ESP32 if I want. * Week 15 only adds the web server next to it. * ============================================================================= */ #include #include "Network.h" #include "WiFi.h" #include // NEW for Week 15: small built-in HTTP server NetworkUDP udp; WebServer server(80); // NEW for Week 15: HTTP server on port 80 // Wi-Fi access point — same credentials as Week 11 const char* ssid = "YaroUDP"; const char* password = "12345678"; IPAddress local_IP(192, 168, 4, 1); IPAddress gateway(192, 168, 4, 1); IPAddress subnet(255, 255, 255, 0); const uint16_t udpPort = 1234; // On-board user LED on the XIAO ESP32-C3 is GPIO 21, active LOW const int LED_PIN = 21; bool ledState = false; // ---- The webpage ---------------------------------------------------------- // One button. Clicking it calls /toggle on the same board. // Keeping it as a single string here is the simplest possible setup. const char HTML_PAGE[] PROGMEM = R"HTML( YaroLED

YaroLED

)HTML"; // ---- HTTP handlers -------------------------------------------------------- // When the browser asks for "/" — send the HTML page. void handleRoot() { server.send_P(200, "text/html", HTML_PAGE); } // When the button calls "/toggle" — flip the LED and reply OK. void handleToggle() { ledState = !ledState; digitalWrite(LED_PIN, ledState ? LOW : HIGH); // LOW = ON (active LOW) Serial.println(ledState ? "LED ON" : "LED OFF"); server.send(200, "text/plain", "OK"); } // ---- Setup ---------------------------------------------------------------- void setup() { Serial.begin(115200); delay(1000); // LED pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); // start OFF // Wi-Fi access point — exactly like Week 11 Network.begin(); WiFi.mode(WIFI_AP); WiFi.softAPConfig(local_IP, gateway, subnet); WiFi.softAP(ssid, password); // UDP listener — exactly like Week 11 udp.begin(udpPort); // NEW for Week 15: register the two URLs and start the web server server.on("/", handleRoot); server.on("/toggle", handleToggle); server.begin(); Serial.println("Ready"); Serial.print("AP IP: "); Serial.println(WiFi.softAPIP()); // 192.168.4.1 Serial.println("Open http://192.168.4.1 in your browser"); } // ---- Loop ----------------------------------------------------------------- void loop() { // NEW for Week 15: let the web server handle any incoming HTTP requests server.handleClient(); // Week 11 UDP listener — kept exactly as it was int packetSize = udp.parsePacket(); if (packetSize) { char incoming[255]; int len = udp.read(incoming, sizeof(incoming) - 1); if (len > 0) incoming[len] = '\0'; Serial.print("Received UDP: "); Serial.println(incoming); } }