feat: add PWA frontend for CYD ThermoPro dashboard
Add a Flask backend + SQLite + HTML/CSS/JS PWA that: - Polls the CYD /api/latest endpoint - Stores readings, sessions, and freeform notes in SQLite - Displays probe cards with target setpoints and preset options - Renders temperature history with Chart.js - Serves a PWA manifest and dark-themed dashboard Also update cyd-bridge/README.md with verified bringup instructions.
This commit is contained in:
+61
-42
@@ -5,51 +5,37 @@ Firmware for an ESP32 "Cheap Yellow Display" (ESP32-2432S028R) that reads temper
|
||||
## Hardware
|
||||
|
||||
- **Board:** ESP32-2432S028R
|
||||
- 320×240 TFT (ILI9341 driver)
|
||||
- 320×240 TFT (ILI9341 driver, detected via `LGFX_AUTODETECT`)
|
||||
- Resistive touch panel (XPT2046)
|
||||
- ESP32-WROOM-32 with 4 MB flash
|
||||
- **Thermometer:** ThermoPro TP25 / TP25W / TP920 / TP930 / TP960
|
||||
|
||||
## Firmware architecture
|
||||
## What it does
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ CYD (ESP32-2432S028R) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌──────────────┐ │
|
||||
│ │ ThermoPro │ │ HTTP API │ │
|
||||
│ │ BLE client │─────▶│ Web server │ │
|
||||
│ └─────────────┘ └──────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────────────────────┐ │
|
||||
│ │ SettingsManager (NVS/Preferences)│ │
|
||||
│ └──────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────┐ │
|
||||
│ │ Touch UI: status + setup screens │ │
|
||||
│ └──────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
- Connects the CYD to your WiFi network.
|
||||
- Scans for a ThermoPro thermometer by its advertised service UUID (`1086FFF0-3343-4817-8BB2-B32206336CE8`) and connects over BLE.
|
||||
- Decodes battery level, connection status, and up to four probe temperatures.
|
||||
- Runs a small HTTP API that any frontend (web app, mobile app, Home Assistant, etc.) can consume.
|
||||
- Shows a simple touch dashboard with probe temperatures and connection status.
|
||||
|
||||
## API endpoints
|
||||
|
||||
- `GET /api/health` — device health and connectivity status.
|
||||
- `GET /api/latest` — latest ThermoPro reading.
|
||||
- `GET /api/settings` — current settings (excluding WiFi password).
|
||||
- `POST /api/settings` — update settings (JSON body).
|
||||
- `GET /` — setup page when in AP mode; status page when in STA mode.
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/health` | Device health and connectivity status. |
|
||||
| `GET` | `/api/latest` | Latest ThermoPro reading. |
|
||||
| `GET` | `/api/settings` | Current settings (WiFi password omitted). |
|
||||
| `POST` | `/api/settings` | Update settings (JSON body). |
|
||||
| `GET` | `/` | Setup page in AP mode; status page in STA mode. |
|
||||
|
||||
## Endpoints response examples
|
||||
|
||||
### `GET /api/latest`
|
||||
### `GET /api/latest` example
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"deviceId": "cyd-smoker",
|
||||
"device": "ThermoPro TP930",
|
||||
"mac": "C9:48:1D:B1:E1:E7",
|
||||
"mac": "c9:48:1d:b1:e1:e7",
|
||||
"connected": true,
|
||||
"battery": 90,
|
||||
"unit": "F",
|
||||
@@ -60,8 +46,9 @@ Firmware for an ESP32 "Cheap Yellow Display" (ESP32-2432S028R) that reads temper
|
||||
{ "id": 3, "name": "Probe 3", "temperature": null, "connected": false },
|
||||
{ "id": 4, "name": "Probe 4", "temperature": null, "connected": false }
|
||||
],
|
||||
"readingTime": "2026-07-19T12:00:00+00:00",
|
||||
"bridgeTime": "2026-07-19T12:00:01+00:00"
|
||||
"readingTime": "12345",
|
||||
"bridgeTime": "12346",
|
||||
"source": "cyd-bridge"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,9 +57,10 @@ Firmware for an ESP32 "Cheap Yellow Display" (ESP32-2432S028R) that reads temper
|
||||
1. **First boot:** the CYD starts a captive portal AP named `CYD-ThermoPro-Setup`.
|
||||
2. Connect to the AP with a phone or laptop and open `http://192.168.4.1`.
|
||||
3. Enter your home WiFi SSID and password, plus the ThermoPro MAC address.
|
||||
4. The device connects to WiFi, stores the credentials, and reboots into normal mode.
|
||||
4. The device saves the credentials and reboots into normal mode.
|
||||
5. Find the CYD's local IP from your router or the serial monitor, then open `http://<cyd-ip>/api/latest`.
|
||||
|
||||
Runtime settings (endpoint, token, probe names, units, polling interval) can be changed through the same web UI at the device's local IP or via the JSON API.
|
||||
**Note on MAC addresses:** If you previously paired the thermometer with the official ThermoPro app, the app may show a *resolved* public-looking MAC while the device actually advertises with a *random* BLE address. The CYD scans by the ThermoPro service UUID, so it will find the device regardless. Enter whatever address the app displays; the UUID match takes priority.
|
||||
|
||||
## Building and flashing
|
||||
|
||||
@@ -94,26 +82,57 @@ If you have not installed PlatformIO yet:
|
||||
pip install platformio
|
||||
```
|
||||
|
||||
## First-time hardware check
|
||||
### First-time upload
|
||||
|
||||
Before relying on the dashboard, verify the pinout matches your exact board revision:
|
||||
If the CYD is not detected:
|
||||
|
||||
1. Open `src/display/DisplayConfig.hpp`.
|
||||
2. Confirm `TFT_CS`, `TFT_DC`, `TFT_RST`, `TFT_BL`, `TOUCH_CS`, and the SPI pins match the silkscreen or schematic of your ESP32-2432S028R.
|
||||
3. If the screen stays white or touch is inverted, adjust `cfg.offset_rotation` in `DisplayConfig.hpp` or `setRotation()` in `Dashboard::begin()`.
|
||||
1. Try both USB ports; only one is wired to the UART chip.
|
||||
2. Install the USB-to-serial driver if Windows shows an unknown device:
|
||||
- CH340/CH343: [WCH driver](https://www.wch-ic.com/downloads/CH343SER_ZIP.html)
|
||||
- CP2102: [Silicon Labs driver](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers)
|
||||
3. If the upload still fails, hold the **BOOT** button, press and release **RST**, then release **BOOT**, and retry.
|
||||
|
||||
## Memory usage
|
||||
|
||||
With the default partition table the firmware uses approximately:
|
||||
|
||||
- **RAM:** ~18 % (~58 kB of 320 kB)
|
||||
- **Flash:** ~92 % (~1.2 MB of 1.3 MB)
|
||||
- **Flash:** ~96 % (~1.2 MB of 1.3 MB)
|
||||
|
||||
There is enough headroom to run, but large future features (e.g. local graphing, OTA) may require switching to a larger app partition or dropping unused NimBLE options.
|
||||
|
||||
## Runtime settings
|
||||
|
||||
Change settings by POSTing JSON to `/api/settings`:
|
||||
|
||||
```bash
|
||||
curl -X POST http://192.168.2.55/api/settings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"probeNames": ["Brisket", "Ambient", "Probe 3", "Probe 4"],
|
||||
"unit": "F",
|
||||
"deviceId": "cyd-smoker"
|
||||
}'
|
||||
```
|
||||
|
||||
Available fields:
|
||||
|
||||
- `wifiSsid`, `wifiPass`
|
||||
- `thermoproMac`
|
||||
- `deviceId`
|
||||
- `probeNames` (array of 4 strings)
|
||||
- `unit` (`"F"` or `"C"`)
|
||||
|
||||
## Development notes
|
||||
|
||||
- LovyanGFX driver/pin configuration lives in `src/display/DisplayConfig.hpp` and is tuned for the ESP32-2432S028R variant.
|
||||
- Display pinout is handled by `LGFX_AUTODETECT`, which detects the common `Sunton_2432S028` (ILI9341) layout.
|
||||
- BLE uses `NimBLE-Arduino` to leave enough RAM for the web server and UI.
|
||||
- The CYD connects to the ThermoPro by scanning for the advertised service UUID. This is more reliable than MAC matching when the thermometer uses BLE privacy/random addresses.
|
||||
- All user settings are stored in ESP32 NVS via `Preferences`.
|
||||
- The firmware compiles successfully in PlatformIO; the remaining work is on-device testing and pinout verification.
|
||||
- Serial log runs at 115200 baud for diagnostics.
|
||||
|
||||
## Known issues / next steps
|
||||
|
||||
- `/api/latest` timestamps are device-relative millis; wall-clock time would require NTP.
|
||||
- Touch dashboard is minimal; a nicer layout, settings menu, and local alerts are planned.
|
||||
- Flash usage is tight due to `LGFX_AUTODETECT`; a hardcoded board config would free space.
|
||||
|
||||
Reference in New Issue
Block a user