# TODO: # - auto turn off # - navigation bar at bottom # - buttons for home assistant actions substitutions: device_name: kinderhandy friendly_name: Kinder Handy esphome: name: $device_name friendly_name: $friendly_name esp32: board: esp32dev framework: type: arduino logger: api: encryption: key: !secret api_encryption_key wifi: ssid: WLAN password: !secret wifi_password # ============================================================ # Hardware # ============================================================ light: - platform: monochromatic output: backlight_pwm name: Display Backlight id: display_backlight restore_mode: ALWAYS_ON spi: - id: tft clk_pin: GPIO14 mosi_pin: GPIO13 miso_pin: GPIO12 - id: touch clk_pin: GPIO25 mosi_pin: GPIO32 miso_pin: GPIO39 # Setup a pin to control the backlight output: - platform: ledc pin: GPIO21 id: backlight_pwm display: - platform: ili9xxx model: ili9341 spi_id: tft cs_pin: GPIO15 dc_pin: GPIO2 invert_colors: false color_palette: 8BIT # Set up the xpt2046 touch platform touchscreen: platform: xpt2046 spi_id: touch cs_pin: GPIO33 interrupt_pin: GPIO36 update_interval: never threshold: 400 calibration: x_min: 280 x_max: 3850 y_min: 190 y_max: 3765 transform: swap_xy: false mirror_x: true on_release: - if: condition: lvgl.is_paused then: - logger.log: "LVGL resuming" - lvgl.resume: - lvgl.widget.redraw: - light.turn_on: display_backlight # on_touch: # - lambda: |- # ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d", # touch.x, # touch.y, # touch.x_raw, # touch.y_raw # ); # ============================================================ # Globals # ============================================================ globals: - id: timer_seconds type: int initial_value: '120' - id: timer_running type: bool initial_value: 'false' # ============================================================ # Variables # ============================================================ number: - platform: template name: LVGL Screen timeout optimistic: true id: display_timeout unit_of_measurement: "s" initial_value: 45 restore_value: true min_value: 10 max_value: 180 step: 5 mode: box # ============================================================ # Display # ============================================================ lvgl: on_idle: timeout: !lambda "return (id(display_timeout).state * 1000);" then: - logger.log: "LVGL is idle" - light.turn_off: display_backlight - lvgl.pause: buffer_size: 50% widgets: - label: align: TOP_MID y: 10 text: "Lukas und Hannas\nZahnputz Timer" text_font: montserrat_20 - container: id: arc_container align: CENTER y: 20 width: 240 height: 240 on_press: then: - if: condition: lambda: 'return id(timer_running);' then: - globals.set: id: timer_running value: 'false' - logger.log: format: "Pause" - lvgl.arc.update: id: arc_timer indicator: arc_color: 0x0000EE else: - globals.set: id: timer_running value: 'true' - logger.log: format: "Gestartet" - lvgl.arc.update: id: arc_timer value: !lambda return id(timer_seconds); indicator: arc_color: 0xFF0000 on_long_press: then: - globals.set: id: timer_seconds value: '120' - globals.set: id: timer_running value: 'false' - lvgl.arc.update: id: arc_timer value: 0 indicator: arc_color: 0xFF0000 - lvgl.label.update: id: timer_label text: !lambda 'return std::string("02:00");' - logger.log: format: "Timer reset (long press)" widgets: - arc: id: arc_timer align: CENTER width: 220 height: 220 min_value: 0 max_value: 120 value: 0 arc_width: 8 arc_color: 0x404040 # Indicator arc styling (the progress) indicator: arc_width: 20 arc_opa: COVER arc_color: 0xFF0000 # Start with red - label: id: timer_label align: CENTER text_font: montserrat_28 text: "02:00" interval: - interval: 1s then: - if: condition: lambda: 'return id(timer_running);' then: - globals.set: id: timer_seconds value: !lambda 'return max(0, (int)id(timer_seconds) - 1);' - lvgl.arc.update: id: arc_timer value: !lambda 'return (int)(id(timer_seconds));' indicator: arc_color: !lambda | float f = (120.0 - (float)id(timer_seconds)) / 120.0; if (f < 0) f = 0; if (f > 1) f = 1; if (f <= 0.5) { // Red to Yellow (f: 0.0 to 0.5) float t = f / 0.5; int r = 255; int g = (int)(255 * t + 0.5); int b = 0; int hex = (r << 16) | (g << 8) | b; return lv_color_hex(hex); } else { // Yellow to Green (f: 0.5 to 1.0) float t = (f - 0.5) / 0.5; int r = (int)(255 * (1.0 - t) + 0.5); int g = 255; int b = 0; int hex = (r << 16) | (g << 8) | b; return lv_color_hex(hex); } - lambda: |- ESP_LOGI("timer", "timer_seconds=%d fraction=%.2f", id(timer_seconds), (float)id(timer_seconds)/120.0); - lvgl.label.update: id: timer_label text: !lambda 'char buf[6]; sprintf(buf, "%02d:%02d", id(timer_seconds)/60, id(timer_seconds)%60); return std::string(buf);' - if: condition: lambda: 'return id(timer_seconds) <= 0;' then: - globals.set: id: timer_running value: 'false' - logger.log: format: "Timer finished" - lvgl.arc.update: id: arc_timer value: 120 indicator: arc_color: 0x00FF00