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.
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
- 320×240 TFT (ILI9341 driver, detected via
- 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
- First boot: the CYD starts a captive portal AP named
CYD-ThermoPro-Setup. - Connect to the AP with a phone or laptop and open
http://192.168.4.1. - Enter your home WiFi SSID and password, plus the ThermoPro MAC address.
- The device saves the credentials and reboots into normal mode.
- 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:
- Try both USB ports; only one is wired to the UART chip.
- Install the USB-to-serial driver if Windows shows an unknown device:
- CH340/CH343: WCH driver
- CP2102: Silicon Labs driver
- 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,wifiPassthermoproMacdeviceIdprobeNames(array of 4 strings)unit("F"or"C")
Development notes
- Display pinout is handled by
LGFX_AUTODETECT, which detects the commonSunton_2432S028(ILI9341) layout. - BLE uses
NimBLE-Arduinoto 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/latesttimestamps 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.