esphome: 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 logger: level: DEBUG # Explicitly set logging level to DEBUG # Enable Home Assistant API api: # Allow Over-The-Air updates ota: platform: esphome wifi: ssid: "DNTD" password: "wifipassword" ap: ssid: "Mini-Display-Tv--Yellow" password: "wifipassword" 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 - platform: neopixelbus name: "WS2812B LED" id: ws2812b pin: GPIO15 # Keeping WS2812B on GPIO15 num_leds: 1 # Adjust the number of LEDs as per your setup type: GRB # Set the color order if needed (e.g., GRB for WS2812B) variant: WS2812 # Specify the variant (WS2812 for WS2812B) effects: - pulse: - pulse: name: "Fast Pulse" transition_length: 0.5s update_interval: 0.5s min_brightness: 0% max_brightness: 100% - pulse: name: "Slow Pulse" transition_length: 500ms update_interval: 2s - pulse: name: "Asymmetrical Pulse" transition_length: on_length: 1s off_length: 500ms update_interval: 1.5s - random: name: Random Effect With Custom Values transition_length: 5s update_interval: 7s - strobe: name: Strobe Effect With Custom Values colors: - state: true brightness: 100% red: 100% green: 90% blue: 0% duration: 500ms - state: false duration: 250ms - state: true brightness: 100% red: 0% green: 100% blue: 0% duration: 500ms - flicker: name: Flicker Effect With Custom Values alpha: 95% intensity: 3.3% i2c: sda: GPIO5 # D1 scl: GPIO4 # D2 scan: true # Define a sensor to grab the temperature from Home Assistant weather entity sensor: - platform: homeassistant id: temperature entity_id: weather.home 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 - platform: homeassistant id: weather_condition 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 model: "SH1106 128x64" id: sh1106_display update_interval: 1s address: 0x3C # Default I2C address for SH1106 lambda: |- 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_PULLUP name: "Button GPIO12" - platform: gpio pin: number: GPIO13 mode: INPUT_PULLUP name: "Button GPIO13" - platform: gpio pin: number: GPIO14 mode: INPUT_PULLUP 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" interval: - interval: 5s then: - lambda: |- id(page) = (id(page) + 1) % 6;