# 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). ## Recommended approach: Arduino / PlatformIO C++ firmware 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 - `unit` — `F` 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.