Files
Device-Framework/README.md
T

5.0 KiB
Raw 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
  • 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 5× power-cycle clears all settings and restarts
  • Config persistence — all settings stored as JSON in LittleFS (/config.json)

Building and flashing

The project uses PlatformIO.

# Build
pio run

# Flash
pio run --target upload

# Open serial monitor (115200 baud)
pio device monitor

Board target: 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).
  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

If you lose the web UI password or need to clear all settings, reset the device 5 times in quick succession (press EN or cycle power 5× within a few seconds, before boot completes). All settings are wiped and the device restarts into the Wi-Fi captive portal.

Serial output shows the progress:

[BOOT] reset count 1/5
[BOOT] reset count 2/5
...
[BOOT] reset count 5/5, triggering factory reset
[BOOT] factory reset triggered!
[BOOT] factory reset complete, restarting...

Web UI

Browse to the device address to open the configuration page.

Info panel

Shows the current hostname and IP address.

Hostname

Sets the mDNS name (<hostname>.local) and the MQTT client ID. Saved across reboots.

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.


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

GET /

Returns the HTML configuration page.

POST /config

Saves all configuration submitted by the HTML form. Redirects back to /.


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().