substitutions: arrow_up_icon: "\U0000e91f" arrow_down_icon: "\U0000e920" stop_icon: "\U0000e91c" shutter_open_icon: "\U0000e91e" shutter_close_icon: "\U0000e91d" sensor: # Shutter Current Position - platform: homeassistant id: ${shutter_widget_name}_shutter_current_pos entity_id: "${shutter_entity}" attribute: current_position on_value: then: - script.execute: ${shutter_widget_name}_shutter_state_update - lambda: |- int pos = round(id(${shutter_widget_name}_shutter_current_pos).state / 10) * 10; static const char* glyphs[] = { "\U0000e91d", // 0 - shutter_closed "\U0000e93d", // 10 "\U0000e93e", // 20 "\U0000e93f", // 30 "\U0000e940", // 40 "\U0000e941", // 50 "\U0000e93c", // 60 "\U0000e943", // 70 "\U0000e944", // 80 "\U0000e942", // 90 "\U0000e91e" // 100 - shutter_open }; int idx = pos / 10; if (idx < 0) idx = 0; if (idx > 10) idx = 10; lv_label_set_text(id(${shutter_widget_name}_shutter_icon), glyphs[idx]); lv_label_set_text(id(${shutter_widget_name}_shutter), glyphs[idx]); text_sensor: # Shutter Name - platform: homeassistant id: ${shutter_widget_name}_shutter_name entity_id: "${shutter_entity}" attribute: friendly_name on_value: - lvgl.label.update: id: ${shutter_widget_name}_shutter_label_name text: !lambda return x; # Shutter State - platform: homeassistant id: ${shutter_widget_name}_shutter_state entity_id: "${shutter_entity}" on_value: then: - script.execute: id: ${shutter_widget_name}_get_and_set_translated_state state_str: !lambda 'return id(${shutter_widget_name}_shutter_state).state;' - lvgl.label.update: id: ${shutter_widget_name}_shutter_label_state y: 5 align: TOP_MID - if: condition: lambda: 'return x == "opening";' then: - lvgl.widget.show: ${shutter_widget_name}_shutter_label_pos - if: condition: lambda: 'return x == "closing";' then: - lvgl.widget.show: ${shutter_widget_name}_shutter_label_pos - if: condition: lambda: 'return x == "open";' then: - lvgl.widget.show: ${shutter_widget_name}_shutter_label_pos - if: condition: lambda: 'return x == "closed";' then: - lvgl.widget.hide: ${shutter_widget_name}_shutter_label_pos - lvgl.label.update: id: ${shutter_widget_name}_shutter_label_state y: 0 align: CENTER lvgl: pages: - id: ${shutter_widget_name}_shutter_page bg_color: color_slate_blue_gray widgets: - obj: id: ${shutter_widget_name}_shutter_bg_state x: -20 y: 40 width: 320 height: 54 align: TOP_RIGHT bg_opa: transp pad_all: 0 border_opa: TRANSP border_width: 0 shadow_opa: TRANSP radius: 10 widgets: - label: id: ${shutter_widget_name}_shutter_label_state y: 5 align: TOP_MID text_font: nunito_16 text_color: color_misty_blue text: " " - label: id: ${shutter_widget_name}_shutter_label_pos y: -5 align: BOTTOM_MID text_font: nunito_16 text_color: color_misty_blue text: " " - obj: id: ${shutter_widget_name}_shutter_bg_controls x: 20 y: 20 width: 100 height: 320 align: TOP_LEFT # bg_color: color_steel_blue bg_opa: transp pad_all: 0 border_opa: TRANSP border_width: 0 shadow_opa: TRANSP radius: 10 widgets: - obj: y: 20 width: 90 height: 90 align: top_mid pad_all: 0 bg_opa: transp shadow_opa: transp border_opa: transp widgets: - obj: width: 70 height: 70 align: center clickable: true radius: 50 pad_all: 0 bg_opa: transp border_opa: transp border_width: 0 shadow_width: 8 shadow_spread: 2 shadow_color: color_black pressed: bg_color: 0x3A3A4C shadow_width: 5 on_press: - homeassistant.action: action: cover.open_cover data: entity_id: "${shutter_entity}" - obj: width: 60 height: 60 align: center clickable: false radius: 45 pad_all: 0 bg_opa: transp border_opa: transp shadow_width: 4 shadow_color: 0xFFFFFF shadow_ofs_x: -4 shadow_ofs_y: -2 shadow_opa: 30% - obj: width: 65 height: 65 pad_all: 0 align: center clickable: false radius: 50 border_opa: transp bg_color: color_slate_blue_gray widgets: - label: align: CENTER text_font: icons_32 text_color: color_misty_blue text: "${arrow_up_icon}" - obj: width: 90 height: 90 align: center pad_all: 0 bg_opa: transp shadow_opa: transp border_opa: transp widgets: - obj: width: 70 height: 70 align: center clickable: true radius: 50 pad_all: 0 bg_opa: transp border_opa: transp border_width: 0 shadow_width: 8 shadow_spread: 2 shadow_color: color_black pressed: bg_color: 0x3A3A4C shadow_width: 5 on_press: - homeassistant.action: action: cover.stop_cover data: entity_id: "${shutter_entity}" - obj: width: 60 height: 60 align: center clickable: false radius: 45 pad_all: 0 bg_opa: transp border_opa: transp shadow_width: 4 shadow_color: 0xFFFFFF shadow_ofs_x: -4 shadow_ofs_y: -2 shadow_opa: 30% - obj: width: 65 height: 65 pad_all: 0 align: center clickable: false radius: 50 border_opa: transp bg_color: color_slate_blue_gray widgets: - label: align: CENTER text_font: icons_32 text_color: color_misty_blue text: "${stop_icon}" - obj: y: -20 width: 90 height: 90 align: bottom_mid pad_all: 0 bg_opa: transp shadow_opa: transp border_opa: transp widgets: - obj: width: 70 height: 70 align: center clickable: true radius: 50 pad_all: 0 bg_opa: transp border_opa: transp border_width: 0 shadow_width: 8 shadow_spread: 2 shadow_color: color_black pressed: bg_color: 0x3A3A4C shadow_width: 5 on_press: - homeassistant.action: action: cover.close_cover data: entity_id: "${shutter_entity}" - obj: width: 60 height: 60 align: center clickable: false radius: 45 pad_all: 0 bg_opa: transp border_opa: transp shadow_width: 4 shadow_color: 0xFFFFFF shadow_ofs_x: -4 shadow_ofs_y: -2 shadow_opa: 30% - obj: width: 65 height: 65 pad_all: 0 align: center clickable: false radius: 50 border_opa: transp bg_color: color_slate_blue_gray widgets: - label: align: CENTER text_font: icons_32 text_color: color_misty_blue text: "${arrow_down_icon}" - obj: id: ${shutter_widget_name}_shutter_bg_slider x: -20 y: 94 width: 320 height: 310 align: TOP_RIGHT # bg_color: color_steel_blue bg_opa: transp pad_all: 0 border_opa: transp border_width: 0 shadow_opa: TRANSP radius: 10 widgets: - label: id: ${shutter_widget_name}_shutter_icon align: CENTER text_font: icons_300 text_color: color_misty_blue text: "\U0000e91d" - slider: id: ${shutter_widget_name}_shutter_set_pos_slider hidden: false radius: 0 bg_opa: TRANSP y: -32 align: BOTTOM_MID width: 210 height: 220 min_value: 0 max_value: 100 indicator: bg_opa: TRANSP radius: 0 knob: bg_opa: TRANSP on_value: then: - script.execute: id: ${shutter_widget_name}_shutter_slider_preview_update value: !lambda 'return x;' on_release: - homeassistant.action: action: cover.set_cover_position data: entity_id: "${shutter_entity}" position: !lambda return int(x); - obj: id: ${shutter_widget_name}_shutter_back x: 20 y: 360 width: 100 height: 100 align: TOP_LEFT bg_opa: transp pad_all: 0 border_opa: TRANSP border_width: 0 shadow_opa: TRANSP radius: 10 widgets: - obj: width: 90 height: 90 align: center pad_all: 0 bg_opa: transp shadow_opa: transp border_opa: transp widgets: - obj: width: 70 height: 70 align: center clickable: true radius: 10 pad_all: 0 bg_opa: transp border_opa: transp border_width: 0 shadow_width: 8 shadow_spread: 2 shadow_color: color_black pressed: bg_color: 0x3A3A4C shadow_width: 5 on_press: then: - lvgl.widget.show: menu_controls_main - lvgl.page.show: id: shutter_group_page animation: OUT_RIGHT time: 300ms - label: id: ${shutter_widget_name}_shutter_back_label align: center text_font: icons_28 text_color: color_misty_blue text: "${exit_icon}" - obj: id: ${shutter_widget_name}_shutter_bg_name x: -20 y: 400 width: 320 height: 36 align: TOP_RIGHT bg_opa: transp pad_all: 0 border_opa: TRANSP border_width: 0 shadow_opa: TRANSP radius: 10 widgets: - label: id: ${shutter_widget_name}_shutter_label_name align: CENTER text_font: nunito_16 text_color: color_misty_blue text: "shutter" script: - id: ${shutter_widget_name}_shutter_state_update then: - lvgl.slider.update: id: ${shutter_widget_name}_shutter_set_pos_slider value: !lambda |- return round(id(${shutter_widget_name}_shutter_current_pos).state / 10) * 10; - lvgl.label.update: id: ${shutter_widget_name}_shutter_label_pos text: !lambda |- return to_string((int)id(${shutter_widget_name}_shutter_current_pos).state) + "%"; - id: ${shutter_widget_name}_shutter_slider_preview_update parameters: value: int then: - lvgl.label.update: id: ${shutter_widget_name}_shutter_label_pos text: !lambda |- return to_string((int)value) + "%"; - lambda: |- int pos = round(value / 10) * 10; static const char* glyphs[] = { "\U0000e91d", // 0 - shutter_closed "\U0000e93d", // 10 "\U0000e93e", // 20 "\U0000e93f", // 30 "\U0000e940", // 40 "\U0000e941", // 50 "\U0000e93c", // 60 "\U0000e943", // 70 "\U0000e944", // 80 "\U0000e942", // 90 "\U0000e91e" // 100 - shutter_open }; int idx = pos / 10; if (idx < 0) idx = 0; if (idx > 10) idx = 10; lv_label_set_text(id(${shutter_widget_name}_shutter_icon), glyphs[idx]); lv_label_set_text(id(${shutter_widget_name}_shutter), glyphs[idx]); - id: ${shutter_widget_name}_get_and_set_translated_state parameters: state_str: string then: - lambda: |- std::string state = state_str; auto it = id(cover_translations).find(state); std::string translated_state = (it != id(cover_translations).end()) ? it->second : state; lv_label_set_text(id(${shutter_widget_name}_shutter_label_state), translated_state.c_str()); select: - platform: lvgl widget: language_dropdown id: ${shutter_widget_name}_select_language on_value: then: - delay: 300ms - script.execute: id: ${shutter_widget_name}_get_and_set_translated_state state_str: !lambda 'return id(${shutter_widget_name}_shutter_state).state;' esphome: on_boot: priority: -100 then: - if: condition: lambda: 'return id(${shutter_widget_name}_shutter_state).has_state();' then: - script.execute: id: ${shutter_widget_name}_get_and_set_translated_state state_str: !lambda 'return id(${shutter_widget_name}_shutter_state).state;' api: on_client_connected: - if: condition: lambda: 'return id(${shutter_widget_name}_shutter_state).has_state();' then: - script.execute: id: ${shutter_widget_name}_get_and_set_translated_state state_str: !lambda 'return id(${shutter_widget_name}_shutter_state).state;'