Files
2026-06-29 01:10:47 +02:00

6.1 KiB
Raw Permalink Blame History

ESP32 Device Framework

A reusable ESP32 firmware base with Wi-Fi, web configuration UI, authentication, MQTT / Home Assistant integration, and factory reset. Add device-specific logic on top without re-implementing the boilerplate.

Table of contents


Features

  • Wi-Fi via WiFiManager — captive-portal setup on first boot, credentials stored in flash
  • mDNS — device reachable as <hostname>.local
  • Web UI — responsive configuration page served from the device, with logo support
  • Authentication — optional HTTP Basic Auth to protect the web UI
  • MQTT — connects to any broker, publishes an availability topic, reconnects automatically without blocking the web server
  • Home Assistant discovery — stub ready for your entities
  • Factory reset — rapid power-cycling clears settings (5× config, 10× config + Wi-Fi credentials)
  • Config persistence — all settings stored as JSON in LittleFS (/config.json)

Building and flashing

The project uses PlatformIO.

# Build
pio run -e esp32dev

# Flash firmware
pio run -e esp32dev --target upload

# Upload filesystem image (logo, etc.) — only needed when data/ changes
pio run -e esp32dev --target uploadfs

# Open serial monitor (115 200 baud)
pio device monitor

Note: close the serial monitor before uploading — it holds the serial port exclusively.

Board targets: esp32dev, esp32-s3-devkitc-1


First-time Wi-Fi setup

On first boot (or when stored Wi-Fi credentials are missing), the device starts an access point named ESP32-Device. Connect to it with any phone or laptop — a captive portal will appear automatically.

  1. Enter your Wi-Fi SSID and password.
  2. Optionally change the Device hostname (default: esp32-device, max 63 characters).
  3. Click Save. The device connects to your network and restarts.

After connecting, the device is reachable at:

  • http://<hostname>.local (default http://esp32-device.local) — mDNS, works on most local networks
  • http://<IP address> — shown in the serial monitor on boot

Factory reset

Power-cycle (or press EN) rapidly before the 3-second boot window expires. The reset counter accumulates across rapid reboots:

Cycles Effect
5 9 Clears hostname, auth, and MQTT config; restarts into normal Wi-Fi
10+ Clears all of the above plus stored Wi-Fi credentials; restarts into captive portal

Serial output shows the accumulated count:

[BOOT] reset count 3
[BOOT] reset count 4
...
[BOOT] reset count 5, triggering factory reset
[BOOT] factory reset triggered (clearWifi=0)!
[BOOT] factory reset complete, restarting...

Web UI

Browse to the device address to open the configuration page.

Place a logo.png in the data/ directory and upload the filesystem image once. The logo appears in the top-left of the configuration page. The data/logo.png included in this repo is a 200×200 px transparent PNG.

Info panel

Shows the current hostname and IP address.

Hostname

Sets the mDNS name (<hostname>.local). Changing the hostname automatically restarts the device so mDNS re-registers with the new name.

Security

Field Description
Require password Enables HTTP Basic Auth on the web UI
Password Password for the admin account. Leave blank to keep the existing password

MQTT

Field Description
Enable Toggle MQTT on/off
Broker Hostname or IP of your MQTT broker
Port Default 1883
User / Pass Broker credentials (leave Pass blank to keep the existing value)
Prefix Topic prefix (default device)

Click Save to persist all settings. Click Reset Device to restart the device immediately.


MQTT / Home Assistant

Connection behaviour

On connect the device publishes online to <prefix>/status (retained) and sets offline as the LWT. If the broker is unreachable, the firmware probes the TCP port before attempting a full MQTT connect and retries every 30 seconds without blocking the web server.

Extending with discovery and topics

Three stubs in main.cpp are the intended extension points:

Function Purpose
mqttSubscribe() Subscribe to command topics after connecting
mqttCallback() Handle incoming messages
mqttPublishDiscovery() Publish Home Assistant discovery payloads

HTTP API

Method Path Description
GET / HTML configuration page
GET /logo.png Logo image served from LittleFS
POST /config Save configuration; redirects to /. Restarts if hostname changed
POST /reset Restart the device immediately

Configuration reference

Config is stored as JSON in LittleFS at /config.json.

{
  "hostname": "esp32-device",
  "mqtt": {
    "en": true,
    "host": "192.168.1.10",
    "port": 1883,
    "user": "ha",
    "pass": "secret",
    "prefix": "device"
  },
  "auth": {
    "en": true,
    "pass": "secret"
  }
}

The file is written by the web UI. To erase everything including flash, use pio run --target erase.


Extending the framework

  1. Add your hardware setup in setup() after the framework initialises.
  2. Add your per-loop logic in loop() alongside server.handleClient() and mqttLoop().
  3. Fill in the three MQTT stubs to subscribe, receive, and publish discovery payloads.
  4. Add extra web routes with server.on(...) in startServer() if you need device-specific endpoints.
  5. Persist extra config fields by adding keys to loadConfig() and saveConfig().
  6. Place static files (images, etc.) in data/ and upload the filesystem image with pio run --target uploadfs.