- Scan for ThermoPro by advertised service UUID instead of relying only on MAC, solving resolvable-private-address issues after phone pairing. - Defer connect until after the scan is fully stopped to avoid NimBLE race. - Add connect cleanup, state-name diagnostics, and main-loop retry. - Switch display config to LGFX_AUTODETECT for correct CYD pinout. - Verified: CYD connects to ThermoPro and receives temperature notifications.
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)
- Resistive touch panel (XPT2046)
- ESP32-WROOM-32 with 4 MB flash
- Thermometer: ThermoPro TP25 / TP25W / TP920 / TP930 / TP960
Firmware architecture
┌─────────────────────────────────────────┐
│ CYD (ESP32-2432S028R) │
│ │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ ThermoPro │ │ HTTP API │ │
│ │ BLE client │─────▶│ Web server │ │
│ └─────────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ SettingsManager (NVS/Preferences)│ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Touch UI: status + setup screens │ │
│ └──────────────────────────────────┘ │
└─────────────────────────────────────────┘
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.
Endpoints response examples
GET /api/latest
{
"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": "2026-07-19T12:00:00+00:00",
"bridgeTime": "2026-07-19T12:00:01+00:00"
}
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 connects to WiFi, stores the credentials, and reboots into normal mode.
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.
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 hardware check
Before relying on the dashboard, verify the pinout matches your exact board revision:
- Open
src/display/DisplayConfig.hpp. - Confirm
TFT_CS,TFT_DC,TFT_RST,TFT_BL,TOUCH_CS, and the SPI pins match the silkscreen or schematic of your ESP32-2432S028R. - If the screen stays white or touch is inverted, adjust
cfg.offset_rotationinDisplayConfig.hpporsetRotation()inDashboard::begin().
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)
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.
Development notes
- LovyanGFX driver/pin configuration lives in
src/display/DisplayConfig.hppand is tuned for the ESP32-2432S028R variant. - BLE uses
NimBLE-Arduinoto leave enough RAM for the web server and UI. - 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.