substitutions: name: sthome-ut9 friendly_name: "sthome-ut9" #ALLOWED_CHARACTERS_FULL: " !#%\"'()+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]_abcdefghijklmnopqrstuvwxyz{|}°²³µ¿ÁÂÄÅÉÖÚßàáâãäåæçèéêëìíîðñòóôõöøùúûüýþāăąćčďĐđēėęěğĮįıļľŁłńňőřśšťũūůűųźŻżŽžơưșțΆΈΌΐΑΒΓΔΕΖΗΘΚΜΝΠΡΣΤΥΦάέήίαβγδεζηθικλμνξοπρςστυφχψωϊόύώАБВГДЕЖЗИКЛМНОПРСТУХЦЧШЪЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёђєіїјљњћ" ALLOWED_CHARACTERS: " !#%\"'()+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]_abcdefghijklmnopqrstuvwxyz{|}°²³µ•" esphome: name: "${name}" friendly_name: "${friendly_name}" on_boot: - lvgl.widget.hide: ind_geyser_on - delay: 5s - lvgl.widget.hide: boot_screen esp32: board: esp32dev framework: type: arduino #type: esp-idf #debug: # update_interval: 5s # Enable logging logger: level: info # Enable Home Assistant API api: encryption: key: "LI7j37zs9HsWNsUZ5c83leThmhHsgIVReAPoc9U6pVU=" on_client_connected: - if: condition: lambda: 'return (0 == client_info.find("Home Assistant "));' then: - lvgl.widget.show: lbl_hastatus - lvgl.widget.show: lbl_degree on_client_disconnected: - if: condition: lambda: 'return (0 == client_info.find("Home Assistant "));' then: - lvgl.widget.hide: lbl_hastatus - lvgl.widget.hide: ind_geyser_on - lvgl.widget.hide: lbl_degree ota: - platform: esphome password: "8ebd5bcefbdc833a5f6ddc4e8ba56e39" wifi: #ssid: !secret wifi_ssid #password: !secret wifi_password # we will use local dns server for local dns resolution power_save_mode: none domain: ".sthome.org" networks: - ssid: !secret wifi_ssid1 password: !secret wifi_password1 - ssid: !secret wifi_ssid2 password: !secret wifi_password2 - ssid: !secret wifi_ssid3 password: !secret wifi_password3 - ssid: !secret wifi_ssid4 password: !secret wifi_password4 - ssid: !secret wifi_ssid5 password: !secret wifi_password5 manual_ip: # For faster connection startup, set a static IP address # Set this to the IP of the ESP static_ip: 10.0.2.9 gateway: 10.0.0.2 subnet: 255.255.240.0 dns1: 10.0.0.1 dns2: 1.1.1.1 # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "${name} Fallback Hotspot" password: "iZxjpw7ucRs4" captive_portal: #psram: one_wire: - platform: gpio pin: GPIO4 id: temperature_sensors #i2c: # sda: GPIO21 # scl: GPIO22 font: # - file: "fonts/Windows/comic.ttf" # id: comic # size: 20 # bpp: 4 #2 # - file: "fonts/misc/tom-thumb.bdf" # id: tomthumb # # # gfonts://family[@weight] # - file: "gfonts://Roboto" # id: roboto_20 # size: 20 # # - file: # type: gfonts # family: Roboto # weight: 900 # id: roboto_20 # size: 20 # # - file: "fonts/Windows/arial.ttf" # id: arial_14 # size: 14 # # gfonts://family[@weight] # - file: "gfonts://Roboto" # id: roboto # size: 20 - file: "gfonts://Carrois Gothic" id: Carrois_Gothic size: 20 bpp: 4 - file: "gfonts://Roboto" id: geyser_temperature_font1 size: 200 bpp: 4 glyphs: [ 0123456789,.,°,a,n, "\u0020", # space ] - file: "gfonts://Roboto" id: geyser_temperature_font2 size: 60 bpp: 4 glyphs: [ °,C, ] - file: "gfonts://Roboto" id: geyser_temperature_font3 size: 30 bpp: 4 glyphs: [ b,o,m,p,t, ] # - file: "gfonts://Merriweather" # id: Merriweather # size: 30 # # - file: "gfonts://Material+Symbols+Outlined" # id: icons_50 # size: 50 # glyphs: ["\U0000e425"] # mdi-timer # # - file: "fonts/roboto/Roboto-Condensed.ttf" # id: roboto_special_28 # size: 28 # bpp: 4 # glyphs: [ # 0123456789aAáÁeEéÉ, # (,),+,-,_,.,°,•,µ, # "\u0020", # space # "\u002C", # , # "\u0021", # ! # "\u0022", # " # "\u0027", # ' # "\u003A", # : # ] # # - file: "fonts/roboto/Roboto-Condensed.ttf" # id: roboto_special_32 # size: 32 # bpp: 4 # glyphs: [ # 0123456789aAáÁeEéÉ, # (,),+,-,_,.,°,•,µ, # "\u0020", # space # "\u002C", # , # "\u0021", # ! # "\u0022", # " # "\u0027", # ' # "\u003A", # : # ] # # - file: "fonts/roboto/Roboto-Condensed.ttf" # id: roboto_special_36 # size: 36 # bpp: 4 # glyphs: [ # 0123456789aAáÁeEéÉ, # (,),+,-,_,.,°,•,µ, # "\u0020", # space # "\u002C", # , # "\u0021", # ! # "\u0022", # " # "\u0027", # ' # "\u003A", # : # ] # ## - file: "fonts/RobotoCondensed-Regular.ttf" ## id: my_font_with_icons ## size: 20 ## bpp: 4 ## extras: ## - file: "fonts/misc/materialdesignicons-webfont.ttf" ## glyphs: [ ## "\U000F02D1", # mdi-heart ## "\U000F05D4", # mdi-airplane-landing ## ] # # - file: # type: gfonts # family: Roboto # id: roboto_european_core # size: 16 # glyphsets: # - GF_Latin_Core # - GF_Greek_Core # - GF_Cyrillic_Core # # - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" # id: web_font # size: 20 # - file: # url: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" # type: web # id: web_font2 # size: 24 # - file: "gfonts://Roboto@500" # id: font_small # size: 14 # glyphs: ${ALLOWED_CHARACTERS} # - file: "gfonts://Roboto@500" # id: font_medium # size: 24 # glyphs: ${ALLOWED_CHARACTERS} # - file: "gfonts://Roboto@500" # id: font_large # size: 40 # glyphs: ${ALLOWED_CHARACTERS} # - file: "gfonts://Roboto@500" # id: font_extra_large # size: 60 # glyphs: [Z] - file: "https://github.com/AlmostInteractive/ESP32-S3-Box-3-Voice-Assistant-Sensor-Dock/raw/master/fonts/materialdesignicons-webfont.ttf" id: font_icon_tiny size: 30 glyphs: [ "\U000F009A",#bell "\U000F009C",#bell-outline "\U000F00AD",#block-helper "\U000F01F2",#emoticon-outline "\U000F0375",#minus-box "\U000F0416",#plus-box ] - file: "fonts/misc/materialdesignicons-webfont.ttf" id: font_icon_small size: 24 #45 glyphs: [ "\U0000F5A9", # "\U000F0079",#battery 100% # "\U000F0082",#battery 90% # "\U000F0081",#battery 80% # "\U000F0080",#battery 70% # "\U000F007F",#battery 60% # "\U000F007E",#battery 50% # "\U000F007D",#battery 40% # "\U000F007C",#battery 30% # "\U000F007B",#battery 20% # "\U000F007A",#battery 10% # "\U000F10CD",#battery warning # "\U000F050F",#temp sensor # "\U000F16BD",#wifi connected # "\U000F16BC",#wifi disconnected # "\U000F07D0",#api connected # "\U000F12A8",#touch button # "\U000F0EBA",#stats # "\U000F087B",#api disconnected # "\U000F057E",#speaker on # "\U000F0581",#speaker off # "\U000F0493",#settings cog # "\U000F06E8",#light bulb illuminated # "\U000F0335",#light bulb off # "\U000F0A19",#toggle off # "\U000F0521",#toggle on # "\U000F032E",#led-variant-off # "\U000F0330",#led-variant-outline # "\U000F004F",#arrow-left-bold-circle # "\U000F0056",#arrow-right-bold-circle # "\U000F0375",#minus-box # "\U000F0416",#plus-box # "\U000F009A",#bell # "\U000F00AD",#block-helper # "\U000F01F2",#emoticon-outline ] - file: "https://github.com/AlmostInteractive/ESP32-S3-Box-3-Voice-Assistant-Sensor-Dock/raw/master/fonts/materialdesignicons-webfont.ttf" id: font_icon_large size: 65 glyphs: [ "\U000F004F",#arrow-left-bold-circle "\U000F0056",#arrow-right-bold-circle ] image: - file: https://esphome.io/_static/favicon-512x512.png id: boot_logo resize: 200x200 type: RGB565 transparency: alpha_channel - file: "images/fire.svg" id: img_fire resize: 25x25 type: RGB565 transparency: alpha_channel - file: "images/fire-red.svg" id: img_fire_red resize: 100x100 # 25x25 type: RGB565 transparency: alpha_channel # - file: "images/thermometer2.png" # id: thermometer_img # type: RGB565 # transparency: alpha_channel color: - id: green hex: '75D15F' - id: red hex: 'FF3131' - id: blue hex: '47B7E9' - id: blue_light hex: 'CFE2F3' - id: blue_dark hex: '085296' - id: amber hex: 'FBAB35' - id: lime hex: '20FC30' - id: pink hex: 'D92BBC' - id: yellow hex: 'FFC000' - id: black hex: '000000' - id: white hex: 'ffffff' - id: purple hex: '73264D' - id: grey_dark hex: '202020' #ads1115: # - address: 0x48 # id: ads1115_48 # continuous_mode: true # - address: 0x49 # id: ads1115_49 # continuous_mode: true # - address: 0x4A # id: ads1115_4A # continuous_mode: true # # - address: 0x4B # # id: ads1115_4B #psram: sun: id: sun_sensor latitude: !secret latitude longitude: !secret longitude #time: # - platform: sntp # timezone: Africa/Johannesburg # servers: # - ntp1.meraka.csir.co.za # 146.64.24.58 # - ntp.as3741.net # 196.4.160.4 # - ntp1.inx.net.za # 196.10.52.57 time: - platform: homeassistant id: time_source update_interval: 360min # Change sync interval from default 5min to 6 hours on_time_sync: then: - if: # Publish the time the device was last restarted, but only once. condition: lambda: 'return id(device_last_restart).state == "";' then: - text_sensor.template.publish: id: device_last_restart state: !lambda 'return id(time_source).now().strftime("%a %d %b %Y - %I:%M:%S %p");' - script.execute: testing_values - script.execute: time_update on_time: - minutes: '*' seconds: '*' then: - script.execute: testing_values - script.execute: time_update - hours: 2,3,4,5,17 minutes: 5 seconds: 0 then: - switch.turn_on: switch_antiburn - hours: 2,3,4,5,17 minutes: 35 seconds: 0 then: - switch.turn_off: switch_antiburn spi: - id: spi_bus0 clk_pin: GPIO18 mosi_pin: GPIO23 miso_pin: GPIO19 interface: any display: - platform: ili9xxx model: ili9488 id: tft_display color_palette: 8BIT data_rate: 40MHz cs_pin: GPIO15 dc_pin: GPIO2 reset_pin: GPIO27 auto_clear_enabled: false update_interval: never invert_colors: false show_test_card: true transform: swap_xy: true # landscape # mirror_x: true # landscape dimensions: height: 480 width: 320 # Define a PWM output on the ESP32 output: - platform: ledc pin: GPIO26 id: backlight_pwm # Define a monochromatic, dimmable light for the backlight light: - platform: monochromatic output: backlight_pwm name: "Display Backlight" id: back_light restore_mode: ALWAYS_ON touchscreen: platform: xpt2046 id: touch_screen cs_pin: GPIO33 transform: swap_xy: true # landscape # mirror_y: true # portrait calibration: x_min: 231 #201 #281 x_max: 3878 #3793 #3848 y_min: 221 #228 #347 y_max: 3861 #3914 #3878 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 ); on_release: then: - if: condition: lvgl.is_paused then: - lvgl.resume: - lvgl.widget.redraw: lvgl: # color_depth: 16 # bg_color: 0x0F0F0F default_font: unscii_8 # align: center theme: button: bg_color: 0x2F8CD8 bg_grad_color: 0x005782 bg_grad_dir: VER bg_opa: COVER border_color: 0x0077b3 border_width: 1 text_color: 0xFFFFFF pressed: # set some button colors to be different in pressed state bg_color: 0x006699 bg_grad_color: 0x00334d checked: # set some button colors to be different in checked state bg_color: 0x1d5f96 bg_grad_color: 0x03324A text_color: 0xfff300 buttonmatrix: bg_opa: TRANSP border_color: 0x0077b3 border_width: 0 text_color: 0xFFFFFF pad_all: 0 items: # set all your buttonmatrix buttons to use your custom defined styles and font bg_color: 0x2F8CD8 bg_grad_color: 0x005782 bg_grad_dir: VER bg_opa: COVER border_color: 0x0077b3 border_width: 1 text_color: 0xFFFFFF text_font: montserrat_16 #Carrois_Gothic pressed: bg_color: 0x006699 bg_grad_color: 0x00334d checked: bg_color: 0x1d5f96 bg_grad_color: 0x03324A text_color: 0x005580 switch: bg_color: 0xC0C0C0 bg_grad_color: 0xb0b0b0 bg_grad_dir: VER bg_opa: COVER checked: bg_color: 0x1d5f96 bg_grad_color: 0x03324A bg_grad_dir: VER bg_opa: COVER knob: bg_color: 0xFFFFFF bg_grad_color: 0xC0C0C0 bg_grad_dir: VER bg_opa: COVER slider: border_width: 1 border_opa: 15% bg_color: 0xcccaca bg_opa: 15% indicator: bg_color: 0x1d5f96 bg_grad_color: 0x03324A bg_grad_dir: VER bg_opa: COVER knob: bg_color: 0x2F8CD8 bg_grad_color: 0x005782 bg_grad_dir: VER bg_opa: COVER border_color: 0x0077b3 border_width: 1 text_color: 0xFFFFFF style_definitions: - id: header_footer bg_color: 0x2F8CD8 bg_grad_color: 0x005782 bg_grad_dir: VER bg_opa: COVER border_opa: TRANSP radius: 0 pad_all: 0 pad_row: 0 pad_column: 0 border_color: 0x0077b3 text_color: 0xFFFFFF width: 100% height: 30 - id: clockdate_style text_font: montserrat_20 #roboto_20 #unscii_8 text_align: center text_color: 0x000000 # bg_opa: cover radius: 4 pad_all: 2 displays: - tft_display buffer_size: 20% top_layer: widgets: - label: text: "\U0000F5A9" # "\uF1EB" id: lbl_hastatus hidden: true align: top_right x: -2 y: 1 text_font: font_icon_small #montserrat_16 text_align: right text_color: 0x202020 # 0xFFFFFF - image: id: ind_geyser_on align: BOTTOM_RIGHT #TOP_RIGHT src: img_fire_red x: 15 # -25 y: 7 #1 height: 100 #25 width: 100 #25 - obj: id: boot_screen x: 0 y: 0 width: 100% height: 100% bg_color: 0xffffff bg_opa: COVER radius: 0 pad_all: 0 border_width: 0 widgets: - image: align: CENTER src: boot_logo y: -40 - spinner: align: CENTER y: 95 height: 50 width: 50 spin_time: 1s arc_length: 60deg arc_width: 8 indicator: arc_color: 0x18bcf2 arc_width: 8 on_press: - lvgl.widget.hide: boot_screen pages: # - id: pg_geyser_temperature # widgets: # image: # align: CENTER # src: thermometer_img # bg_color: 0xff0000 # bg_opa: true - id: pg_clock widgets: - obj: # clock container height: 310 #SIZE_CONTENT width: 310 # 100% align: CENTER pad_all: 0 border_width: 0 bg_color: 0xFFFFFF widgets: - meter: # clock face height: 310 width: 310 align: CENTER bg_opa: TRANSP border_width: 0 text_color: 0x000000 scales: - range_from: 0 # minutes scale range_to: 720 angle_range: 360 rotation: 270 ticks: width: 1 count: 61 length: 10 color: 0x000000 indicators: - line: id: minute_hand width: 3 color: 0xa6a6a6 r_mod: -4 value: 0 - range_from: 1 # hours scale for labels range_to: 12 angle_range: 330 rotation: 300 ticks: width: 1 count: 12 length: 1 major: stride: 1 width: 4 length: 10 color: 0xC0C0C0 label_gap: 12 - range_from: 0 # hi-res hours scale for hand range_to: 720 angle_range: 360 rotation: 270 ticks: count: 0 indicators: - line: id: hour_hand width: 5 color: 0xa6a6a6 r_mod: -30 value: 0 # Second hand - angle_range: 360 rotation: 270 range_from: 0 range_to: 60 indicators: - line: id: second_hand width: 2 color: Red r_mod: -10 - label: align: CENTER styles: clockdate_style id: day_label y: -50 - label: align: CENTER id: date_label styles: clockdate_style y: 50 - id: pg_geyser_temp widgets: - obj: id: rect_gtoptemp x: 0 y: 0 #30 pad_all: 0 height: 320 #290 width: 240 align: TOP_LEFT bg_color: 0x000000 border_color: 0xFFFFFF border_width: 1 radius: 0 bg_opa: COVER - obj: id: rect_gbottemp y: 0 pad_all: 0 height: 320 #290 width: 240 align_to: id: rect_gtoptemp align: out_right_top x: 0 y: 0 #12.5% bg_color: 0x000000 #0xFF4500 border_color: 0xFFFFFF border_width: 1 radius: 0 bg_opa: COVER - label: text: " " id: lbl_gtoptemp hidden: false align: LEFT_MID x: 0 y: -10 text_font: geyser_temperature_font1 text_align: center text_color: 0x0 bg_opa: LV_OPA_TRANSP bg_color: 0xffffff - label: text: " " id: lbl_gbottemp hidden: false align: RIGHT_MID x: 0 y: -10 text_font: geyser_temperature_font1 text_align: center text_color: 0x0 bg_opa: LV_OPA_TRANSP bg_color: 0xffffff - label: text: "°C" id: lbl_degree hidden: false align: BOTTOM_MID x: 0 y: 0 text_font: geyser_temperature_font2 text_align: center text_color: 0x0 bg_opa: LV_OPA_TRANSP bg_color: 0xffffff - label: text: "top" id: lbl_top hidden: false align: TOP_MID x: -120 y: 20 text_font: geyser_temperature_font3 text_align: center text_color: 0x0 bg_opa: LV_OPA_TRANSP bg_color: 0xffffff - label: text: "bottom" id: lbl_bottom hidden: false align: TOP_MID x: 120 y: 20 text_font: geyser_temperature_font3 text_align: center text_color: 0x0 bg_opa: LV_OPA_TRANSP bg_color: 0xffffff - id: pg_settings widgets: - textarea: id: geyser_schedule one_line: true placeholder_text: "Enter text here" - keyboard: id: keyboard_id textarea: geyser_schedule mode: TEXT_UPPER text_font: montserrat_20 on_focus: then: - lvgl.keyboard.update: id: keyboard_id mode: number textarea: geyser_schedule on_ready: then: - logger.log: Keyboard is ready on_cancel: then: - logger.log: Keyboard cancelled # - id: clock2_page # width: 100% # bg_color: Black # widgets: # # Outer Clock Container # - obj: # height: 300 #470 # width: 300 #470 # align: center # pad_all: 4 # bg_color: Black # border_width: 0 # widgets: # - meter: # height: 100% # width: 100% # align: center # bg_color: White # # scales: # # Minor ticks # - ticks: # width: 2 # count: 61 # length: 10 # color: Black # range_from: 0 # range_to: 3600 #60 # angle_range: 360 # rotation: 270 # # # Minute hand # indicators: # - line: # id: minute_hand # width: 3 # color: Black # r_mod: -1 # # # Major ticks # - angle_range: 330 # rotation: 300 # range_from: 1 # range_to: 12 # ticks: # width: 3 # count: 12 # length: 20 # color: Black # # # Hour hand # - angle_range: 360 # rotation: 270 # range_from: 0 # range_to: 720 # indicators: # - line: # id: hour_hand # width: 4 # color: Black # r_mod: -40 # # # Second hand # - angle_range: 360 # rotation: 270 # range_from: 0 # range_to: 60 # indicators: # - line: # id: second_hand # width: 2 # color: Red # r_mod: -10 # - image: # align: CENTER # src: cat_image # id: img_id # radius: 11 # clip_corner: true # - platform: ssd1306_i2c # model: "SSD1306 128x64" ## reset_pin: GPIO32 # address: 0x3C # id: oled_display # pages: # - id: page1 # lambda: |- # auto time_obj = id(time_source).now(); # auto date = time_obj.strftime("%Y-%m-%d"); # auto time = time_obj.strftime("%H:%M:%S"); # it.print(0, 0, id(roboto_16), date.c_str()); # it.print(0, 20, id(roboto_special_36), time.c_str()); # - id: page2 # lambda: |- # // Print WiFi Signal # it.printf(0, 26, id(arial_14), "Wi-Fi: %.1fdBm", id(wifi_sig).state); # // Print time in HH:MM format # it.strftime(0, 0, id(roboto), TextAlign::TOP_LEFT, "%H:%M", id(time_source).now()); # //// Print Room humidity"(from xiaomi sensor) # //if (id(room_humidity).has_state()) { # // it.printf(127,62, id(roboto), TextAlign::BOTTOM_RIGHT, "%.1f%%", id(room_humidity).state); # //} # // Print Study temperature(from dallas sensor) # if (id(study_temperature).has_state()) { # it.printf(127, 0, id(Carrois_Gothic), TextAlign::TOP_RIGHT, "%.1f°C", id(study_temperature).state); # } # - id: page3 # lambda: |- # // Print 29Gal temperature(from dallas sensor) # if (id(study_temperature).has_state()) { # it.printf(64, 10, id(Kdam_Thmor_Pro), TextAlign::CENTER_HORIZONTAL, "%.1f°C", id(study_temperature).state); # } # - id: page4 # lambda: |- # // Print time in HH:MM format # it.strftime(64, 10, id(Kdam_Thmor_Pro), TextAlign::CENTER_HORIZONTAL, "%H:%M", id(time_source).now()); #interval: # - interval: 30s # then: # - display.page.show_next: oled_display # - component.update: oled_display # - lvgl.page.next switch: - platform: restart name: "${name} Restart" id: "restart_switch" - platform: template name: Antiburn id: switch_antiburn icon: mdi:television-shimmer optimistic: true entity_category: "config" turn_on_action: - logger.log: "Starting Antiburn" - if: condition: lvgl.is_paused then: - lvgl.resume: - lvgl.widget.redraw: - lvgl.pause: show_snow: true turn_off_action: - logger.log: "Stopping Antiburn" - if: condition: lvgl.is_paused then: - lvgl.resume: - lvgl.widget.redraw: binary_sensor: - platform: homeassistant name: "Geyser Heating" entity_id: binary_sensor.sthome_ut8_heating id: geyser_heating on_press: then: - lvgl.widget.show: ind_geyser_on on_release: then: - lvgl.widget.hide: ind_geyser_on sensor: - platform: dallas_temp address: 0xfe00000037b3d528 name: "Study Temperature" id: study_temperature update_interval: "60s" resolution: 12 one_wire_id: temperature_sensors unit_of_measurement: "°C" #icon: "mdi:water-thermometer" device_class: "temperature" state_class: "measurement" accuracy_decimals: 1 filters: - filter_out: nan # - sliding_window_moving_average: # window_size: 120 # averages over 120 update intervals # send_every: 60 # reports every 60 update intervals # Report wifi signal strength every 5 min if changed - platform: wifi_signal name: WiFi Signal id: wifi_sig update_interval: 300s filters: - delta: 10% # human readable uptime sensor output to the text sensor above - platform: uptime name: Uptime in Days id: uptime_sensor_days update_interval: 10s on_raw_value: then: - text_sensor.template.publish: id: uptime_human state: !lambda |- int seconds = round(id(uptime_sensor_days).raw_state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; auto days_str = std::to_string(days); auto hours_str = std::to_string(hours); auto minutes_str = std::to_string(minutes); auto seconds_str = std::to_string(seconds); return ( (days ? days_str + "d " : "") + (hours ? hours_str + "h " : "") + (minutes ? minutes_str + "m " : "") + (seconds_str + "s") ).c_str(); # number of seconds since midnight - platform: template id: time_of_day name: "Time of day" accuracy_decimals: 0 unit_of_measurement: "s" lambda: |- auto currenttime = id(time_source).now(); ESPTime time_obj = currenttime; time_obj.second = 0; time_obj.minute = 0; time_obj.hour = 0; time_obj.recalc_timestamp_local(); return currenttime.timestamp - time_obj.timestamp; update_interval: 10s - platform: homeassistant name: "Geyser Top Temperature" entity_id: sensor.sthome_ut8_geyser_top_temperature id: geyser_top_temperature on_raw_value: then: - lvgl.label.update: id: lbl_gtoptemp text: !lambda |- if(isnan(x)) { return "."; } else { char buffer [10]; buffer[0] = '\0'; snprintf (buffer, 10, "%.0f", x); return buffer; } - lvgl.widget.update: id: rect_gtoptemp bg_color: !lambda |- if(isnan(x)) { return lv_color_hex(0x000000); } if(x >= 60) { return lv_color_hex(0xFF0000); } if(x >= 50) { return lv_color_hex(0xFFFF00); } if(x >= 40) { return lv_color_hex(0x00FF00); } return lv_color_hex(0x0000FF); - platform: homeassistant name: "Geyser Bottom Temperature" entity_id: sensor.sthome_ut8_geyser_bottom_temperature id: geyser_bottom_temperature on_raw_value: then: - lvgl.label.update: id: lbl_gbottemp text: !lambda |- if(isnan(x)) { return "."; } else { char buffer [10]; buffer[0] = '\0'; snprintf (buffer, 10, "%.0f", x); return buffer; } - lvgl.widget.update: id: rect_gbottemp bg_color: !lambda |- if(isnan(x)) { return lv_color_hex(0x000000); } if(x < 40) { return lv_color_hex(0x0000FF); } if(x < 50) { return lv_color_hex(0x00FF00); } if(x < 60) { return lv_color_hex(0xFFFF00); } return lv_color_hex(0xFF0000); text_sensor: - platform: template id: module_time name: "Module time" icon: mdi:clock lambda: |- auto time_obj = id(time_source).now(); return time_obj.strftime("%Y-%m-%d %H:%M:%S"); update_interval: 1s # Expose WiFi information as sensors - platform: wifi_info ip_address: name: IP mac_address: name: Mac Address entity_category: diagnostic ssid: name: "Connected SSID" id: ssid entity_category: diagnostic # human readable update text sensor from sensor:uptime - platform: template name: Uptime id: uptime_human icon: mdi:clock-start - platform: template name: 'Last Restart' id: device_last_restart icon: mdi:clock entity_category: diagnostic script: - id: time_update then: - lvgl.indicator.update: id: minute_hand value: !lambda |- auto now = id(time_source).now(); return now.minute * 12 + now.second/5; - lvgl.indicator.update: id: hour_hand value: !lambda |- auto now = id(time_source).now(); return std::fmod(now.hour, 12) * 60 + now.minute; - lvgl.indicator.update: id: second_hand value: !lambda |- auto now = id(time_source).now(); return now.second; - lvgl.label.update: id: date_label text: !lambda |- static const char * const mon_names[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; static char date_buf[8]; auto now = id(time_source).now(); snprintf(date_buf, sizeof(date_buf), "%s %2d", mon_names[now.month-1], now.day_of_month); return date_buf; - lvgl.label.update: id: day_label text: !lambda |- static const char * const day_names[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; return day_names[id(time_source).now().day_of_week - 1]; - id: testing_values then: - lambda: |- char buffer [10]; auto value = id(geyser_top_temperature).state; buffer[0] = '\0'; snprintf (buffer, 10, "temp: %.0f", value); //ESP_LOGI("test", buffer);