#include "ColorSerial.h" // ANSI Escape Codes const char *ColorSerial::RESET = "\033[0m"; const char *ColorSerial::BOLD = "\033[1m"; const char *ColorSerial::UNDERLINE = "\033[4m"; const char *ColorSerial::ITALIC = "\033[3m"; // Standard Colors const char *ColorSerial::RED = "\033[38;2;255;0;0m"; const char *ColorSerial::GREEN = "\033[38;2;0;255;0m"; const char *ColorSerial::BLUE = "\033[38;2;0;120;255m"; const char *ColorSerial::YELLOW = "\033[38;2;255;255;0m"; const char *ColorSerial::CYAN = "\033[38;2;0;255;255m"; const char *ColorSerial::MAGENTA = "\033[38;2;255;0;255m"; const char *ColorSerial::ORANGE = "\033[38;2;255;165;0m"; const char *ColorSerial::WHITE = "\033[38;2;255;255;255m"; const char *ColorSerial::GRAY = "\033[38;2;128;128;128m"; // Icons const char *ColorSerial::ICON_SUCCESS = "✅"; const char *ColorSerial::ICON_ERROR = "❌"; const char *ColorSerial::ICON_WARNING = "⚠️"; const char *ColorSerial::ICON_INFO = "ℹ️"; const char *ColorSerial::ICON_DEBUG = "🐛"; const char *ColorSerial::ICON_WIFI = "📡"; const char *ColorSerial::ICON_WEATHER = "🌡️"; // Main Logging Methods void ColorSerial::success(const char *message, const char *details) { Serial.print(GREEN); Serial.print(ICON_SUCCESS); Serial.print(" SUCCESS: "); Serial.print(RESET); Serial.print(BOLD); Serial.print(message); Serial.print(RESET); if (strlen(details) > 0) { Serial.print(" "); Serial.print(GRAY); Serial.print("("); Serial.print(details); Serial.print(")"); Serial.print(RESET); } Serial.println(); } void ColorSerial::error(const char *message, const char *details) { Serial.print(RED); Serial.print(ICON_ERROR); Serial.print(" ERROR: "); Serial.print(RESET); Serial.print(BOLD); Serial.print(message); Serial.print(RESET); if (strlen(details) > 0) { Serial.print(" "); Serial.print(RED); Serial.print(details); Serial.print(RESET); } Serial.println(); } void ColorSerial::warning(const char *message, const char *details) { Serial.print(YELLOW); Serial.print(ICON_WARNING); Serial.print(" WARNING: "); Serial.print(RESET); Serial.print(BOLD); Serial.print(message); Serial.print(RESET); if (strlen(details) > 0) { Serial.print(" "); Serial.print(GRAY); Serial.print("("); Serial.print(details); Serial.print(")"); Serial.print(RESET); } Serial.println(); } void ColorSerial::info(const char *message, const char *details) { Serial.print(CYAN); Serial.print(ICON_INFO); Serial.print(" INFO: "); Serial.print(RESET); Serial.print(BOLD); Serial.print(message); Serial.print(RESET); if (strlen(details) > 0) { Serial.print(" "); Serial.print(GRAY); Serial.print("("); Serial.print(details); Serial.print(")"); Serial.print(RESET); } Serial.println(); } void ColorSerial::debug(const char *message, const char *details) { Serial.print(MAGENTA); Serial.print(ICON_DEBUG); Serial.print(" DEBUG: "); Serial.print(RESET); Serial.print(ITALIC); Serial.print(message); Serial.print(RESET); if (strlen(details) > 0) { Serial.print(" "); Serial.print(GRAY); Serial.print("["); Serial.print(details); Serial.print("]"); Serial.print(RESET); } Serial.println(); } // Data Display Methods void ColorSerial::data(const char *label, const char *value, const char *unit) { Serial.print(BLUE); Serial.print(label); Serial.print(":"); Serial.print(RESET); Serial.print(" "); Serial.print(BOLD); Serial.print(WHITE); Serial.print(value); Serial.print(RESET); Serial.print(unit); Serial.println(); } void ColorSerial::data(const char *label, float value, const char *unit) { char buf[20]; snprintf(buf, sizeof(buf), "%.1f", value); data(label, buf, unit); } void ColorSerial::data(const char *label, int value, const char *unit) { char buf[20]; snprintf(buf, sizeof(buf), "%d", value); data(label, buf, unit); } void ColorSerial::temperature(float temp, const char *temp_unit, const char *label) { const char *color; if (temp < 0) color = CYAN; else if (temp < 10) color = BLUE; else if (temp < 20) color = GREEN; else if (temp < 30) color = YELLOW; else color = RED; Serial.print(BLUE); Serial.print(label); Serial.print(": "); Serial.print(RESET); Serial.print(color); Serial.print(temp, 1); Serial.print(temp_unit); Serial.print(RESET); Serial.println(); } void ColorSerial::wifiStatus() { if (WiFi.status() == WL_CONNECTED) { Serial.print(GREEN); Serial.print(ICON_WIFI); Serial.print(" WiFi: "); Serial.print(RESET); Serial.print(BOLD); Serial.print("Connected"); Serial.print(GRAY); Serial.print(" (IP: "); Serial.print(WiFi.localIP().toString().c_str()); Serial.print(")"); Serial.print(RESET); Serial.println(); } else { Serial.print(RED); Serial.print(ICON_WIFI); Serial.print(" WiFi: "); Serial.print(RESET); Serial.print(BOLD); Serial.print("Disconnected"); Serial.print(RESET); Serial.println(); } } // Progress Bars void ColorSerial::progressBar(int percent, const char *label, int width) { int pos = (percent * width) / 100; const char *color = (percent < 30) ? RED : (percent < 70) ? YELLOW : GREEN; Serial.print(BLUE); Serial.print(label); Serial.print(" ["); Serial.print(RESET); for (int i = 0; i < width; i++) { if (i < pos) { Serial.print(color); Serial.print("█"); } else { Serial.print(GRAY); Serial.print("░"); } } Serial.print(RESET); Serial.print(BLUE); Serial.print("] "); Serial.print(color); Serial.print(percent); Serial.print("%"); Serial.print(RESET); Serial.println(); } // Section Headers void ColorSerial::header(const char *title, const char *decorator, int width) { int titleLen = strlen(title); int padding = (width - titleLen - 2) / 2; Serial.println(); // Top line Serial.print(MAGENTA); for (int i = 0; i < width; i++) { Serial.print(decorator); } Serial.print(RESET); Serial.println(); // Title line Serial.print(MAGENTA); Serial.print("|"); Serial.print(RESET); for (int i = 0; i < padding; i++) { Serial.print(" "); } Serial.print(BOLD); Serial.print(title); Serial.print(RESET); Serial.println(); // Bottom line Serial.print(MAGENTA); for (int i = 0; i < width; i++) { Serial.print(decorator); } Serial.print(RESET); Serial.println(); } void ColorSerial::boxHeader(const char *title, int width) { int titleLen = strlen(title); int padding = (width - titleLen - 4) / 2; // -4 für die Box-Ränder Serial.println(); // Top line Serial.print(MAGENTA); Serial.print("╔"); for (int i = 0; i < width - 2; i++) { Serial.print("═"); } Serial.print("╗"); Serial.print(RESET); Serial.println(); // Title line Serial.print(MAGENTA); Serial.print("║"); Serial.print(RESET); for (int i = 0; i < padding; i++) { Serial.print(" "); } Serial.print(BOLD); Serial.print(title); Serial.print(RESET); // Padding nach dem Titel // for (int i = 0; i < (width - titleLen - padding - 4); i++) for (int i = 0; i < (width - titleLen - padding - 2); i++) { Serial.print(" "); } Serial.print(MAGENTA); Serial.print("║"); Serial.print(RESET); Serial.println(); // Bottom line Serial.print(MAGENTA); Serial.print("╚"); for (int i = 0; i < width - 2; i++) { Serial.print("═"); } Serial.print("╝"); Serial.print(RESET); Serial.println(); } void ColorSerial::subheader(const char *title) { Serial.print(CYAN); Serial.print("▶ "); Serial.print(RESET); Serial.print(BOLD); Serial.print(title); Serial.print(RESET); Serial.println(); } // Weather Specific Private Methods const char *ColorSerial::getWeatherCondition(int code) { switch (code) { case 0: return "Clear sky"; case 1: return "Mainly clear"; case 2: return "Partly cloudy"; case 3: return "Overcast"; case 45: case 48: return "Fog"; case 51: case 53: case 55: return "Drizzle"; case 61: case 63: case 65: return "Rain"; case 71: case 73: case 75: return "Snow"; case 95: case 96: case 99: return "Thunderstorm"; default: return "Unknown weather"; } } const char *ColorSerial::getWeatherIcon(int code) { if (code == 0) return "☀️"; if (code <= 2) return "⛅"; if (code == 3) return "☁️"; if (code <= 55) return "🌧️"; if (code <= 65) return "🌧️"; if (code <= 79) return "❄️"; return "🌩️"; } const char *ColorSerial::getWeatherColor(int code) { if (code <= 2) return YELLOW; if (code == 3) return GRAY; if (code <= 55) return CYAN; if (code <= 65) return BLUE; if (code <= 79) return WHITE; return MAGENTA; } void ColorSerial::weatherCondition(int code, const char *customLabel) { const char *label = (customLabel == nullptr || strlen(customLabel) == 0) ? "Condition" : customLabel; const char *condition = getWeatherCondition(code); const char *icon = getWeatherIcon(code); const char *color = getWeatherColor(code); Serial.print(BLUE); Serial.print(label); Serial.print(": "); Serial.print(RESET); Serial.print(color); Serial.print(icon); Serial.print(" "); Serial.print(condition); Serial.print(RESET); Serial.println(); }