From 1eeeb490731a0610e88763e819a4b626ae2442a8 Mon Sep 17 00:00:00 2001 From: void Date: Fri, 4 Apr 2025 16:17:02 +0000 Subject: [PATCH] Update watchwip --- watchwip | 204 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 181 insertions(+), 23 deletions(-) diff --git a/watchwip b/watchwip index 518ea96..714e1a0 100644 --- a/watchwip +++ b/watchwip @@ -28,8 +28,16 @@ wifi: font: - file: "gfonts://Roboto" id: font1 + size: 22 + + - file: "gfonts://Roboto" + id: font2 size: 12 + - file: "gfonts://Roboto" + id: font3 + size: 10 + light: # WS2812B LED strip configuration @@ -97,6 +105,17 @@ sensor: attribute: temperature internal: true + +time: + - platform: homeassistant + id: esptime + +globals: + - id: page + type: int + restore_value: no + initial_value: '0' + # Text sensors for weather and location information text_sensor: # Current weather condition from Home Assistant @@ -105,6 +124,27 @@ text_sensor: entity_id: weather.home # The entity_id for weather condition internal: true + - platform: homeassistant + id: media_title_sensor + entity_id: media_player.devuan + attribute: media_title + + - platform: homeassistant + id: media_artist_sensor + entity_id: media_player.devuan + attribute: media_artist + + - platform: homeassistant + id: home_condition_day_0 + entity_id: sensor.home_condition_day_0 + internal: true + + - platform: homeassistant + id: home_condition_day_1 + entity_id: sensor.home_condition_day_1 + internal: true + + # Display configuration to show the weather condition and location display: - platform: ssd1306_i2c @@ -113,35 +153,147 @@ display: update_interval: 1s address: 0x3C # Default I2C address for SH1106 lambda: |- - // Display current weather condition - it.print(0, 10, id(font1), id(weather_condition).state.c_str()); - - // Display current temperature under the weather condition - String temp_str = "Temp: " + String(static_cast(id(temperature).state)) + " °F"; // Truncate decimal - it.print(0, 20, id(font1), temp_str.c_str()); // Convert the String to a const char* and display it + if (id(page) == 0) { + std::string weather_text = id(weather_condition).state.c_str(); + + // Wrap the weather text if it exceeds 16 characters + if (weather_text.length() > 16) { + it.print(0, 0, id(font1), weather_text.substr(0, 16).c_str()); + it.print(0, 20, id(font1), weather_text.substr(16).c_str()); + } else { + it.print(0, 0, id(font1), weather_text.c_str()); + } + + // Temperature + char temp_str[20]; + snprintf(temp_str, sizeof(temp_str), "%d°F", (int) id(temperature).state); + if (strlen(temp_str) > 16) { + it.print(0, 40, id(font1), temp_str); + } else { + it.print(0, 40, id(font1), temp_str); + } + } + else if (id(page) == 1) { + // Date & Time + std::string time_str = id(esptime).now().strftime("%I:%M %p"); + if (time_str.length() > 16) { + it.print(0, 0, id(font1), time_str.substr(0, 16).c_str()); + it.print(0, 20, id(font1), time_str.substr(16).c_str()); + } else { + it.print(0, 0, id(font1), time_str.c_str()); + } + } + else if (id(page) == 2) { + // Date (e.g., "Wed 04/03") + std::string date_str = id(esptime).now().strftime("%a %m/%d"); + if (date_str.length() > 16) { + it.print(0, 0, id(font1), date_str.substr(0, 16).c_str()); + it.print(0, 20, id(font1), date_str.substr(16).c_str()); + } else { + it.print(0, 0, id(font1), date_str.c_str()); + } + } + else if (id(page) == 3) { + // Retrieve the state of the sensor for today (Day 0) + std::string condition_day_0 = to_string(id(home_condition_day_0).state); + + // Log the state for debugging + ESP_LOGD("custom", "Condition Day 0: %s", condition_day_0.c_str()); + + // Check if the state is available and assign a default value if not + if (condition_day_0.empty()) { + condition_day_0 = "No data"; // Default text if the state is empty + } + + // Create a display string for Day 0 (today) + std::string display_text_0 = "Today: " + condition_day_0; + + // Define the maximum number of characters per line based on display width + const int max_chars_per_line = 24; // Adjusted to 24 characters per line + int start = 0; + int y_offset = 0; // Vertical position for the next line + + // Loop through the display text and split it into lines if needed + while (start < display_text_0.length()) { + // Get the next substring (line) + std::string line = display_text_0.substr(start, max_chars_per_line); + it.print(0, y_offset, id(font3), line.c_str()); // Print each line at the proper position + + // Update start to the next portion of text + start += max_chars_per_line; + y_offset += 10; // Halved vertical space between lines + } + } + else if (id(page) == 4) { + // Retrieve the state of the sensor for tomorrow (Day 1) + std::string condition_day_1 = to_string(id(home_condition_day_1).state); + + // Log the state for debugging + ESP_LOGD("custom", "Condition Day 1: %s", condition_day_1.c_str()); + + // Check if the state is available and assign a default value if not + if (condition_day_1.empty()) { + condition_day_1 = "No data"; // Default text if the state is empty + } + + // Create a display string for Day 1 (tomorrow) + std::string display_text_1 = "Tomorrow: " + condition_day_1; + + // Define the maximum number of characters per line based on display width + const int max_chars_per_line = 24; // Adjusted to 24 characters per line + int start = 0; + int y_offset = 0; // Vertical position for the next line + + // Loop through the display text and split it into lines if needed + while (start < display_text_1.length()) { + // Get the next substring (line) + std::string line = display_text_1.substr(start, max_chars_per_line); + it.print(0, y_offset, id(font3), line.c_str()); // Print each line at the proper position + + // Update start to the next portion of text + start += max_chars_per_line; + y_offset += 10; // Halved vertical space between lines + } + } + + else if (id(page) == 5) { + // Media Title and Artist + std::string media_title = id(media_title_sensor).state.c_str(); + std::string media_artist = id(media_artist_sensor).state.c_str(); + + // Check if either media title or media artist is empty and display "No music playing" + if (media_title.empty() || media_artist.empty()) { + media_title = "No music playing"; // Default message if no music is playing + media_artist.clear(); // Clear artist to prevent extra text + } + + // Display media title + if (media_title.length() > 24) { + it.print(0, 0, id(font3), media_title.substr(0, 16).c_str()); + it.print(0, 10, id(font3), media_title.substr(16).c_str()); // Reduced from 20 to 10 + } else { + it.print(0, 0, id(font3), media_title.c_str()); + } + + // Display media artist if it's not empty + if (!media_artist.empty()) { + if (media_artist.length() > 24) { + it.print(0, 20, id(font3), media_artist.substr(0, 16).c_str()); // Reduced from 40 to 20 + it.print(0, 30, id(font3), media_artist.substr(16).c_str()); // Reduced from 60 to 30 + } else { + it.print(0, 20, id(font3), media_artist.c_str()); // Reduced from 40 to 20 + } + } + } + + # Define pull-up buttons for GPIOs binary_sensor: - platform: gpio pin: number: GPIO12 - mode: INPUT_PULLUPesphome: - name: esphome-web-ad0671 - friendly_name: WATCH - min_version: 2024.11.0 - name_add_mac_suffix: false - -esp8266: - board: esp01_1m - -# Enable logging with debug level -… name: "Button GPIO14" - - platform: gpio - pin: - number: GPIO0 # Boot button on most ESP32 boards mode: INPUT_PULLUP - inverted: true # Inverted because it's typically pulled low when pressed - name: "Boot Button" name: "Button GPIO12" - platform: gpio pin: @@ -158,4 +310,10 @@ esp8266: number: GPIO0 # Boot button on most ESP32 boards mode: INPUT_PULLUP inverted: true # Inverted because it's typically pulled low when pressed - name: "Boot Button" \ No newline at end of file + name: "Boot Button" + +interval: + - interval: 5s + then: + - lambda: |- + id(page) = (id(page) + 1) % 6; \ No newline at end of file