#include "Dashboard.hpp" #include #include namespace cyd { Dashboard::Dashboard(CYD_Display& display, SettingsManager& settings, ThermoproBLE& bleClient) : display_(display), settings_(settings), bleClient_(bleClient) { } void Dashboard::begin() { display_.init(); display_.initBacklight(); display_.setRotation(0); // Portrait 240x320 display_.fillScreen(TFT_BLACK); display_.setTextDatum(middle_center); drawStatusBar_(); for (size_t i = 0; i < 4; ++i) { int x = (i % 2) * 120; int y = 40 + (i / 2) * 110; drawProbeTile_(i, x, y, 120, 110); } drawFooter_("Touch here for settings"); } void Dashboard::update(bool force) { if (!force && millis() - lastUpdateMillis_ < 1000) { return; } lastUpdateMillis_ = millis(); ThermoproReading reading = bleClient_.getReading(); char targetUnit = settings_.getUnit(); if (force || reading.connected != lastBleConnected_ || reading.battery != lastBattery_) { lastBleConnected_ = reading.connected; lastBattery_ = reading.battery; drawStatusBar_(); } for (size_t i = 0; i < 4; ++i) { float raw = reading.rawTemperatures[i]; bool conn = isValidTemperature(raw); float displayTemp = conn ? convertTemperature(raw, reading.deviceUnit, targetUnit) : -9999.0f; if (force || conn != lastConnected_[i] || fabsf(displayTemp - lastTemps_[i]) > 0.05f) { lastConnected_[i] = conn; lastTemps_[i] = displayTemp; int x = (i % 2) * 120; int y = 40 + (i / 2) * 110; drawProbeTile_(i, x, y, 120, 110); } } String footer = "IP: " + WiFi.localIP().toString(); if (WiFi.status() != WL_CONNECTED) { footer = "AP: CYD-ThermoPro-Setup"; } drawFooter_(footer); } bool Dashboard::checkTouch() { uint16_t x, y; if (display_.getTouch(&x, &y)) { // The footer area is at the bottom 40 px of the screen in portrait mode. if (y > 280) { // Debounce: consume all touch events for 300 ms. unsigned long start = millis(); while (display_.getTouch(&x, &y) && millis() - start < 300) { delay(10); } return true; } } return false; } void Dashboard::showMessage(const String& title, const String& line2, const String& line3) { display_.fillScreen(TFT_BLACK); display_.setTextColor(TFT_WHITE, TFT_BLACK); display_.setTextDatum(top_center); display_.setTextSize(2); display_.drawString(title.c_str(), display_.width() / 2, 60); display_.setTextSize(1); if (line2.length()) { display_.drawString(line2.c_str(), display_.width() / 2, 120); } if (line3.length()) { display_.drawString(line3.c_str(), display_.width() / 2, 150); } display_.setTextDatum(middle_center); // restore default } void Dashboard::drawStatusBar_() { int w = display_.width(); display_.fillRect(0, 0, w, 36, TFT_DARKGREY); display_.drawLine(0, 36, w, 36, TFT_LIGHTGREY); ThermoproReading reading = bleClient_.getReading(); // WiFi icon placeholder: small circle + text display_.setTextColor(TFT_WHITE, TFT_DARKGREY); display_.setTextDatum(middle_left); display_.setTextSize(1); display_.drawString("WiFi", 4, 18); String wifiStatus = (WiFi.status() == WL_CONNECTED) ? "OK" : "--"; display_.drawString(wifiStatus.c_str(), 34, 18); // BLE status display_.setTextDatum(middle_right); String ble = reading.connected ? "BLE OK" : "BLE --"; display_.drawString(ble.c_str(), w - 54, 18); // Battery String batt = String(reading.battery) + "%"; display_.drawString(batt.c_str(), w - 4, 18); } void Dashboard::drawProbeTile_(size_t index, int x, int y, int tileW, int tileH) { ThermoproReading reading = bleClient_.getReading(); char targetUnit = settings_.getUnit(); float raw = reading.rawTemperatures[index]; bool connected = isValidTemperature(raw); float temp = connected ? convertTemperature(raw, reading.deviceUnit, targetUnit) : -9999.0f; // Background uint16_t bgColor = (index % 2 == 0) ? TFT_DARKGREY : TFT_BLACK; display_.fillRect(x + 1, y + 1, tileW - 2, tileH - 2, bgColor); display_.drawRect(x, y, tileW, tileH, TFT_LIGHTGREY); // Probe name display_.setTextColor(TFT_WHITE, bgColor); display_.setTextDatum(top_center); display_.setTextSize(1); display_.drawString(settings_.getProbeName(index).c_str(), x + tileW / 2, y + 8); // Temperature display_.setTextSize(2); if (connected) { String t = formatTemperature_(temp); display_.drawString(t.c_str(), x + tileW / 2, y + tileH / 2 - 8); display_.setTextSize(1); display_.drawString((String("°") + targetUnit).c_str(), x + tileW / 2, y + tileH / 2 + 22); } else { display_.setTextColor(TFT_LIGHTGREY, bgColor); display_.drawString("---", x + tileW / 2, y + tileH / 2); } // Connection dot display_.fillCircle(x + tileW - 12, y + 12, 4, connected ? TFT_GREEN : TFT_RED); } void Dashboard::drawFooter_(const String& message) { int y = display_.height() - 40; display_.fillRect(0, y, display_.width(), 40, TFT_NAVY); display_.drawLine(0, y, display_.width(), y, TFT_LIGHTGREY); display_.setTextColor(TFT_WHITE, TFT_NAVY); display_.setTextDatum(middle_center); display_.setTextSize(1); display_.drawString(message.c_str(), display_.width() / 2, y + 20); } String Dashboard::formatTemperature_(float temp) { char buf[12]; snprintf(buf, sizeof(buf), "%.1f", temp); return String(buf); } } // namespace cyd