Skip to content

Instantly share code, notes, and snippets.

@eyaler
Last active July 5, 2025 16:48
Show Gist options
  • Save eyaler/f337e5475dde8a98665162ba430d1379 to your computer and use it in GitHub Desktop.
Save eyaler/f337e5475dde8a98665162ba430d1379 to your computer and use it in GitHub Desktop.
Captive portal for ESP32S3 16MB using Arduino IDE, LittleFS and AsyncWebServer
// Tested with:
// Arduino IDE 2.3.6
// Board manager: esp32 by Espressif Systems 3.2.1
// Libraries:
// Async TCP by ESP32Async 3.4.5
// ESP32 Async WebServer by ESP32Async 3.7.9
#include <DNSServer.h>
#include <ESPAsyncWebServer.h>
#include <WiFi.h>
#include <LittleFS.h>
static const char* AP_SSID = "✡︎ יחד נגלוש ✡︎";
DNSServer dns;
AsyncWebServer server(80);
const String formatBytes(size_t const& bytes) {
return bytes < 1024 ? static_cast<String>(bytes) + " B" : bytes < 1048576 ? static_cast<String>(bytes / 1024.0) + " KB" : static_cast<String>(bytes / 1048576.0) + " MB";
}
void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root) {
Serial.println("- failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println(" - not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.printf(" DIR : %s\n", file.name());
if (levels) {
listDir(fs, file.path(), levels - 1);
}
} else {
Serial.printf(" FILE: %s (%s)\n", file.name(), formatBytes(file.size()).c_str());
}
file = root.openNextFile();
}
}
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println();
if(!LittleFS.begin(true)){
Serial.println("LittleFS mount failed");
while(1) delay(1000);
}
listDir(LittleFS, "/", 2);
Serial.printf("USED: %s, TOTAL: %s, FREE: %s\n", formatBytes(LittleFS.usedBytes()).c_str(), formatBytes(LittleFS.totalBytes()).c_str(), formatBytes(LittleFS.totalBytes() - LittleFS.usedBytes()).c_str());
WiFi.AP.begin();
WiFi.AP.create(AP_SSID);
dns.start();
server.serveStatic("/", LittleFS, "/");
server.onNotFound([](auto *request) {
request->redirect("/index.html");
});
server.begin();
}
void loop() {
dns.processNextRequest();
}
# Name Type SubType Offset Size Flags
nvs data nvs 0x9000 0x5000
otadata data ota 0xE000 0x2000
app0 app ota_0 0x10000 0x200000
spiffs data spiffs 0x210000 0xDE0000
coredump data coredump 0xFF0000 0x10000
@eyaler
Copy link
Author

eyaler commented Jul 5, 2025

detailed setup instructions: https://tfi.la/cap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment