Remove M1730 ammeter code; generalize to ESP32 device framework

This commit is contained in:
2026-06-28 23:37:51 +02:00
parent 757f5f4c06
commit 3c2f99ffad
2 changed files with 645 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
# 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](#features)
- [Building and flashing](#building-and-flashing)
- [First-time Wi-Fi setup](#first-time-wi-fi-setup)
- [Web UI](#web-ui)
- [MQTT / Home Assistant](#mqtt--home-assistant)
- [HTTP API](#http-api)
- [Configuration reference](#configuration-reference)
- [Extending the framework](#extending-the-framework)
---
## 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](https://platformio.org/).
```bash
# 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`.
```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()`.