This document describes the HTTP endpoints exposed by the ESP32 Quectel firmware webserver. Most resources are served from the LittleFS filesystem and some operations operate on the SD card.
| Method | Path | Description |
|---|---|---|
| GET | / |
Home page (index.html) |
| GET | /config |
Configuration page. Add ?skip to mark captive portal accessed. |
| GET | /device-details.html |
Device details page |
| GET | /ota.html |
OTA firmware update page |
| GET | /file-system.html |
File viewer page |
| GET | /advanced-settings.html |
Advanced settings UI |
| GET | /style.css |
Stylesheet |
| GET | /style.min.css |
Minified stylesheet |
| GET | /script.min.js |
Main JavaScript module |
| GET | /images/sensor_logo.png |
Sensor logo image |
| GET | /sensors_logo.png |
Inline PNG asset from header |
| GET | /icons/{name}.svg |
Individual icon files (wifi, simcard, lock, cell_tower) |
- Response: plain text containing the current device ID (e.g.
ESP32-94255ABA2010).
- Response: JSON object from
getDeviceConfig()containing the stored device configuration.
- Response: JSON object mapping SSID strings to info objects:
{ "mywifi": { "rssi": -42, "encType": 3 }, "neighbour": { "rssi": -80, "encType": 0 } }
- Payload: JSON body representing new configuration.
- Behavior: validates JSON, calls
saveConfig(), marks captive portal accessed. - Response:
{ "status":"Config received" }
Example
curl -X POST http://192.168.4.1/save-config \
-H "Content-Type: application/json" \
-d '{"wifi_ssid":"MyNet","wifi_pass":"pw","device_name":"sensor-1"}'{ "status": "Config received" }- Response: JSON object obtained from
getCurrentSensorData():{ "PM": {"PM1":..,"PM2.5":..,"PM10":..}, "DHT": {"temperature":..,"humidity":..} }
Example
curl http://192.168.4.1/sensor-data{
"PM": { "PM1": 5, "PM2.5": 12, "PM10": 18 },
"DHT": { "temperature": 23.4, "humidity": 55 }
}- Description: used by the OTA page to upload a binary file.
- Behavior: stream write to LittleFS; returns status messages at start/end.
- Response: immediate
{"status":"Upload started"}then{"status":"Upload successful"}on completion or errors.
Example
curl -F "firmware=@build/firmware.bin" http://192.168.4.1/upload-firmware- Response: JSON tree of files under
ROOT_DIRon the SD card. Example:{ "SENSORSDATA": { "2026": { "JAN.csv": "file", "FEB.csv": "file" }, "1970": { "JAN.csv": "file" } }, "failed_send_payloads.txt": "file" }
Example
curl http://192.168.4.1/list-files | jq{
"SENSORSDATA": {"2026":{...}},
"failed_send_payloads.txt": "file"
}- Parameters:
file(URL-encoded path relative to SD root). - Behavior: decodes path, normalizes slashes, attempts several variants (with/without leading slash, prefixed by
ROOT_DIR), serves matching file from SD withapplication/octet-streamandContent-Disposition: attachmentheader. - Errors:
400for missing/invalid path,404if file not found.
Example
curl -OJ "http://192.168.4.1/download?file=%2FSENSORSDATA%2F2026%2FMAR.csv"-
Response: JSON representation of
device_infodocument. -
Response: JSON object containing device details
{
"gsm": {
"Network Name": "TelcoX",
"Signal Strength": -72,
"SIM ICCID": "8914800000123456789",
"Model ID": "Quectel‑EG91",
"Firmware Version": "EG91R9M0A03",
"IMEI": "356789012345678"
},
"wifi": {
"SSID": "Home WiFi",
"Signal Strength": -45,
"Encryption Type": "WPA2"
}
}- All unknown routes trigger a
server.onNotFoundhandler:- If
DeviceConfigState.captivePortalAccessedis false, the user is redirected to/config. - Otherwise responds with
404 Not found.
- If
- The backend uses
AsyncWebServerand LittleFS/SD; - File paths are case-sensitive.
- Static assets are baked into the
data/folder and uploaded viauploadfs.
Generated from src/webserver/asyncserver.cpp on 2026-03-07.