Files
Keith Solomon 9e32b1b179 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.
2026-07-20 20:14:48 -05:00
..

CYD ThermoPro Bridge

Firmware for an ESP32 "Cheap Yellow Display" (ESP32-2432S028R) that reads temperature data from a ThermoPro BLE BBQ thermometer and exposes it through a local HTTP API.

Hardware

  • Board: ESP32-2432S028R
    • 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

What it does

  • 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

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.

GET /api/latest example

{
  "ok": true,
  "deviceId": "cyd-smoker",
  "device": "ThermoPro TP930",
  "mac": "c9:48:1d:b1:e1:e7",
  "connected": true,
  "battery": 90,
  "unit": "F",
  "probeCount": 4,
  "probes": [
    { "id": 1, "name": "Brisket", "temperature": 266.2, "connected": true },
    { "id": 2, "name": "Ambient", "temperature": 235.5, "connected": true },
    { "id": 3, "name": "Probe 3", "temperature": null, "connected": false },
    { "id": 4, "name": "Probe 4", "temperature": null, "connected": false }
  ],
  "readingTime": "12345",
  "bridgeTime": "12346",
  "source": "cyd-bridge"
}

Setup workflow

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

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

Requires PlatformIO.

cd cyd-bridge
# Compile only
pio run
# Compile and upload to the CYD
pio run -t upload
# View serial output
pio device monitor

If you have not installed PlatformIO yet:

pip install platformio

First-time upload

If the CYD is not detected:

  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:
  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: ~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:

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

  • 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.
  • 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.