Files
Keith Solomon 9a3a8f9368 Add ThermoPro BLE support and dashboard display
- Implement ThermoproBLE class for handling BLE communication with ThermoPro BBQ thermometer.
- Create ThermoproReading structure to hold thermometer data.
- Develop Dashboard class for displaying thermometer readings and WiFi status on a TFT display.
- Configure display settings and touch input handling.
- Introduce SettingsManager for managing user settings stored in NVS.
- Implement WiFiManager for handling WiFi connections and captive portal setup.
- Add HTML interface for user to input WiFi credentials and ThermoPro MAC address.
- Ensure proper state management for WiFi and BLE connections in the main application loop.
2026-07-19 19:33:18 -05:00

9.2 KiB
Raw Permalink Blame History

CYD ThermoPro Bridge Integration Plan

Goal

Move the BLE reading and HTTP bridging onto an ESP32 "Cheap Yellow Display" (CYD) board so the Linux host is no longer required. Provide a lightweight touch UI on the CYD for initial WiFi setup and runtime settings (ThermoPro MAC, API endpoint, token, polling interval, probe names, temperature unit).

A native Arduino C++ firmware is the best fit for the CYD:

  • Mature ESP32 WiFi, BLE, HTTP, and display libraries.
  • Direct control over the TFT and touch controller.
  • Enough RAM/flash for a small touch UI plus BLE + HTTP at the same time.
  • Large CYD community examples and known pinouts.

Alternatives considered:

  • MicroPython on the ESP32: possible, but the ThermoPro protocol would need a custom async BLE implementation and the touch UI ecosystem is less mature. Not recommended unless you strongly prefer staying in Python.
  • Keep the Linux bridge and use the CYD only as a display: this contradicts the goal of integrating the bridge into the CYD itself.

Milestones / implementation steps

1. Identify the exact CYD variant

CYD boards vary (ESP32-2432S028C, ESP32-3248S035, etc.). We need to confirm:

  • Display controller (ILI9341, ST7789, ST7796) and resolution (common: 320×240, 480×320).
  • Touch controller (usually XPT2046) and whether it shares the SPI bus with the display.
  • Backlight GPIO and whether it needs PWM dimming.
  • Available free GPIOs, power source, and USB/UART programming arrangement.

Deliverable: a docs/CYD_BRINGUP.md file with the exact pinout and a "hello world" sketch that lights up the screen and prints to Serial.

2. Create the firmware project skeleton

New folder: cyd-bridge/.

  • Use PlatformIO (platformio.ini, board = esp32dev, framework = arduino). PlatformIO makes dependency management and library pin versions much easier than the Arduino IDE, but an .ino wrapper can be kept for Arduino IDE users.
  • Recommended partition scheme: default or large_spiffs depending on whether we want to store a local log or OTA images.

Core libraries to add:

  • Display: TFT_eSPI (widely used, simple) or LovyanGFX (faster, more flexible). Choice depends on the exact panel; both need correct driver/pin configuration.
  • Touch: XPT2046_Bitbang or the touch support built into LovyanGFX.
  • UI: start with custom screens drawn with the display library. LVGL is powerful but adds significant complexity and RAM use; defer unless the UI grows beyond a few screens.
  • Network: built-in WiFi, WiFiManager or a small custom captive portal.
  • BLE: NimBLE-Arduino — much lighter than the default Bluedroid stack and sufficient for this custom protocol.
  • HTTP: built-in HTTPClient.
  • JSON: ArduinoJson.
  • Storage: Preferences (NVS) for settings.
  • (Optional later): ArduinoOTA for over-the-air updates.

3. Settings storage with NVS

Create a SettingsManager class backed by Preferences.

Stored fields:

  • wifi_ssid, wifi_pass
  • tp_mac — ThermoPro BLE address
  • api_endpoint — URL to POST readings to
  • api_token — shared secret for X-Bridge-Token
  • interval_sec — default 15
  • unitF or C
  • probe_names[4]
  • device_id — stable bridge identifier

Include load/save/reset-to-defaults, validation, and a version key so we can migrate the settings struct later.

4. WiFi setup UI

First-boot / unconfigured mode:

  • Start an access point named something like CYD-ThermoPro-Setup.
  • Run a captive portal (DNSServer + WebServer) that serves a single HTML form for WiFi SSID and password.
  • On the CYD screen, show the AP name, a URL or QR code, and instructions.
  • After the user submits valid credentials, the device tries to connect, shuts down the AP, and persists the credentials.

Runtime:

  • A "Network" screen reachable from the status UI shows SSID, IP, RSSI, and a button to re-enter setup mode.

Avoid writing a full on-screen keyboard for WiFi credentials; the captive-portal web form is much faster and more reliable.

5. Settings / configuration UI

The on-device touch UI should stay light:

  • Home / status screen: WiFi state, BLE state, API/POST status, battery %, unit, probe temperatures, last update time.
  • Settings menu: list items such as endpoint, token, MAC, interval, unit, probe names, factory reset.
  • Text-heavy fields (endpoint, token, probe names) are easiest to edit through a second web form served by the device on the local network or in setup AP mode. The touch UI can show the current value and a "Edit on phone/PC" button with a URL/QR code.
  • Toggle/picker fields (unit F/C, interval presets, factory reset) can be handled entirely on the touchscreen.

This split keeps the touch code small while giving a full editor for long strings.

6. Port the ThermoPro BLE protocol to C++

Create a ThermoproBLE C++ class using NimBLE-Arduino. Port the protocol logic directly from the working Python thermopro_cli.py:

  • Service UUID: 1086FFF0-3343-4817-8BB2-B32206336CE8
  • Notify characteristic: 1086FFF2-3343-4817-8BB2-B32206336CE8
  • Write characteristic: 1086FFF1-3343-4817-8BB2-B32206336CE8
  • Send the static handshake bytes (01098a7a13b73ed68b67c2a0) and optional timestamp sync.
  • Parse incoming notifications; specifically command 0x30 for temperature data.
  • Decode the custom BCD temperature format and handle sentinel values (-999.0, -100.0, 666.0) as "probe not connected".
  • Maintain latest state: connected, battery, device_unit, probe_count, temperatures[4], last_update.
  • Implement a non-blocking connection loop with exponential backoff, matching the Python connection_loop() behavior.

7. HTTP bridge client

Create a BridgeClient class:

  • On each polling interval, read the latest BLE state.
  • Build a JSON payload matching the existing receiver.php contract using ArduinoJson.
  • POST to the configured endpoint with the X-Bridge-Token header and a 10-second timeout.
  • Track last POST status/time and surface it on the UI.
  • If BLE is disconnected, still POST a "bridge alive" payload with connected: false so the server knows the device is reachable but the thermometer is out of range.

8. Main application loop

Use a small state machine:

  1. SETUP — AP + captive portal if no credentials stored.
  2. CONNECT_WIFI — connect to configured WiFi with timeout and retry.
  3. CONNECT_BLE — start NimBLE scan/connect to the configured MAC.
  4. RUNNING — read BLE, POST readings, refresh UI, handle reconnections.
  5. ERROR — show a readable error screen and retry after a backoff.

Keep everything non-blocking. Each loop() iteration services BLE events, HTTP state, UI input, and WiFi health. Enable the ESP32 task watchdog to recover from hangs.

9. Status dashboard on the CYD

A single main screen is enough for day-to-day use:

  • Header: WiFi icon, BLE icon, battery percentage, current unit (°F/°C).
  • Body: up to 4 probe tiles. Each tile shows the probe name, current temperature or ---, and a visual indicator for connected/disconnected.
  • Footer: last successful POST time/status, local IP, and a tap hint to open settings.

If the screen is landscape 480×320, the four probes can be shown as a 2×2 grid. If it is portrait 320×480, a vertical list works better.

10. Receiver compatibility

The existing receiver.php should accept the same JSON payload unchanged. Two small additions could help the CYD:

  • GET /api/thermopro/health returning HTTP 200 — lets the CYD verify API reachability before POSTing.
  • CORS headers on the readings endpoint if the CYD ever serves its settings UI from the browser while the PHP server is on another origin.

Neither is required for the MVP.

11. Build, flash, and debug workflow

  • Serial logging at 115200 baud with timestamped, human-readable messages.
  • docs/CYD_BRINGUP.md with exact board variant, wiring, PlatformIO library versions, and pio run -t upload steps.
  • .gitignore for PlatformIO build artifacts, .pio/, .vscode/ if generated.
  • Optional: a simple Python script under tools/ to scan for the CYD's IP or to flash the firmware.

12. Post-MVP ideas

  • Over-the-air firmware updates via a web upload page on the CYD.
  • Direct MQTT publishing from the CYD, bypassing the PHP receiver entirely (nice for Home Assistant users).
  • Temperature alarms with on-screen banners and optional buzzer/LED.
  • Local mini graph of recent temperatures using the NDJSON log or SPIFFS.
  • Support for multiple ThermoPro thermometers on one CYD.

Open questions before implementation

  1. Which exact CYD board do you have? Model name, screen resolution, and whether you already know the display/touch drivers will determine the first milestone.
  2. Do you want to keep the PHP receiver as the destination, or is the real end goal to push straight to Home Assistant / MQTT? This affects whether we keep the HTTP bridge client or add MQTT.
  3. Are you comfortable with Arduino C++ / PlatformIO, or should I also sketch a MicroPython alternative? The plan above assumes C++.
  4. Should the CYD itself show a local "smoker dashboard" with temperatures, or is the primary value the bridge plus a setup UI? The plan includes a dashboard, but we can trim it to just setup if you prefer.