Files
nix-config/modules/nixos/homeassistant/services/esphome/cyd-base-ui.yaml
mjallen18 616d357a59 cyd
2026-04-14 17:42:19 -05:00

1078 lines
46 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
############################################################
# CYD Base LVGL UI + scripts layer
# Include via: packages: !include cyd-base-ui.yaml
############################################################
lvgl:
displays:
- my_display
touchscreens:
- touchscreen_id: ts_touch
# Use a 1/10th frame buffer (~15KB) instead of the default full frame (~150KB).
# Required on CYDs without PSRAM. The display is rendered in horizontal strips.
buffer_size: 10%
style_definitions:
- id: style_tile
bg_color: 0xFFFFFF
bg_opa: 95%
radius: 18
border_width: 0
pad_left: 8
pad_right: 8
pad_top: 8
pad_bottom: 8
shadow_width: 0
shadow_opa: 40%
- id: style_tile_disabled
bg_color: 0x3a3a3a
bg_opa: 95%
radius: 18
border_width: 0
pad_left: 8
pad_right: 8
pad_top: 8
pad_bottom: 8
shadow_width: 0
shadow_opa: 25%
- id: style_icon_circle
bg_color: 0xFEC600
bg_opa: COVER
radius: 999
border_width: 0
- id: style_icon_circle_disabled
bg_color: 0x7B7B6F
bg_opa: 95%
radius: 999
border_width: 0
- id: style_room
text_font: headline
text_color: 0xFFFFFF
text_opa: 100%
- id: style_time
text_font: time_label
text_color: 0xFFFFFF
text_opa: 100%
- id: style_title
text_font: label
text_color: 0x000000
text_opa: 100%
- id: style_value
text_font: sublabel
text_color: 0x7A7A7C
text_opa: 100%
- id: style_value_big
text_font: sublabel_big
text_color: 0xFFFFFF
text_opa: 80%
- id: style_title_disabled
text_font: label
text_color: 0xFFFFFF
text_opa: 100%
- id: style_value_disabled
text_font: sublabel
text_color: 0xD9D9D9
text_opa: 100%
pages:
- id: home_page
bg_color: 0x000000
bg_opa: COVER
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: lbl_room
x: 11
y: 14
text: "${ROOM_NAME}"
styles: style_room
- label:
id: lbl_time
align: TOP_RIGHT
x: -11
y: 14
text: ""
styles: style_time
# ---------- TILE 1 ----------
- obj:
id: tile1
x: 9
y: 54
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile1_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile1_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE1_ICON}"
clickable: false
- label:
id: t1_title
x: 48
y: 4
text: "${TILE1_TITLE}"
styles: style_title
clickable: false
- label:
id: t1_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile1_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE1_TYPE}"
tap_action: "${TILE1_TAP_ACTION}"
service: "${TILE1_TAP_SERVICE}"
entity_id: "${TILE1_ENTITY}"
param_key: "${TILE1_TAP_PARAM_KEY}"
param_val: "${TILE1_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile1).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE1_LONGPRESS}";
std::string type = "${TILE1_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE1_TITLE}"
entity: "${TILE1_ENTITY}"
tile_type: "${TILE1_TYPE}"
longpress_mode: "${TILE1_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile1).state;"
off_value: !lambda "return atoi(\"${TILE1_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile1_brightness).state;"
percentage_value: !lambda "return id(tile1_percentage).state;"
icon_text: "${TILE1_ICON}"
slider_bg_color: ${TILE1_BG_DISABLED_COLOR}
slider_fill_color: ${TILE1_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE1_ICON_ACTIVE_COLOR}
# ---------- TILE 2 ----------
- obj:
id: tile2
x: 164
y: 54
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile2_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile2_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE2_ICON}"
clickable: false
- label:
id: t2_title
x: 48
y: 4
text: "${TILE2_TITLE}"
styles: style_title
clickable: false
- label:
id: t2_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile2_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE2_TYPE}"
tap_action: "${TILE2_TAP_ACTION}"
service: "${TILE2_TAP_SERVICE}"
entity_id: "${TILE2_ENTITY}"
param_key: "${TILE2_TAP_PARAM_KEY}"
param_val: "${TILE2_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile2).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE2_LONGPRESS}";
std::string type = "${TILE2_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE2_TITLE}"
entity: "${TILE2_ENTITY}"
tile_type: "${TILE2_TYPE}"
longpress_mode: "${TILE2_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile2).state;"
off_value: !lambda "return atoi(\"${TILE2_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile2_brightness).state;"
percentage_value: !lambda "return id(tile2_percentage).state;"
icon_text: "${TILE2_ICON}"
slider_bg_color: ${TILE2_BG_DISABLED_COLOR}
slider_fill_color: ${TILE2_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE2_ICON_ACTIVE_COLOR}
# ---------- TILE 3 ----------
- obj:
id: tile3
x: 9
y: 114
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile3_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile3_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE3_ICON}"
clickable: false
- label:
id: t3_title
x: 48
y: 4
text: "${TILE3_TITLE}"
styles: style_title
clickable: false
- label:
id: t3_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile3_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE3_TYPE}"
tap_action: "${TILE3_TAP_ACTION}"
service: "${TILE3_TAP_SERVICE}"
entity_id: "${TILE3_ENTITY}"
param_key: "${TILE3_TAP_PARAM_KEY}"
param_val: "${TILE3_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile3).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE3_LONGPRESS}";
std::string type = "${TILE3_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE3_TITLE}"
entity: "${TILE3_ENTITY}"
tile_type: "${TILE3_TYPE}"
longpress_mode: "${TILE3_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile3).state;"
off_value: !lambda "return atoi(\"${TILE3_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile3_brightness).state;"
percentage_value: !lambda "return id(tile3_percentage).state;"
icon_text: "${TILE3_ICON}"
slider_bg_color: ${TILE3_BG_DISABLED_COLOR}
slider_fill_color: ${TILE3_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE3_ICON_ACTIVE_COLOR}
# ---------- TILE 4 ----------
- obj:
id: tile4
x: 164
y: 114
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile4_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile4_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE4_ICON}"
clickable: false
- label:
id: t4_title
x: 48
y: 4
text: "${TILE4_TITLE}"
styles: style_title
clickable: false
- label:
id: t4_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile4_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE4_TYPE}"
tap_action: "${TILE4_TAP_ACTION}"
service: "${TILE4_TAP_SERVICE}"
entity_id: "${TILE4_ENTITY}"
param_key: "${TILE4_TAP_PARAM_KEY}"
param_val: "${TILE4_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile4).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE4_LONGPRESS}";
std::string type = "${TILE4_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE4_TITLE}"
entity: "${TILE4_ENTITY}"
tile_type: "${TILE4_TYPE}"
longpress_mode: "${TILE4_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile4).state;"
off_value: !lambda "return atoi(\"${TILE4_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile4_brightness).state;"
percentage_value: !lambda "return id(tile4_percentage).state;"
icon_text: "${TILE4_ICON}"
slider_bg_color: ${TILE4_BG_DISABLED_COLOR}
slider_fill_color: ${TILE4_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE4_ICON_ACTIVE_COLOR}
# ---------- TILE 5 ----------
- obj:
id: tile5
x: 9
y: 174
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile5_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile5_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE5_ICON}"
clickable: false
- label:
id: t5_title
x: 48
y: 4
text: "${TILE5_TITLE}"
styles: style_title
clickable: false
- label:
id: t5_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile5_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE5_TYPE}"
tap_action: "${TILE5_TAP_ACTION}"
service: "${TILE5_TAP_SERVICE}"
entity_id: "${TILE5_ENTITY}"
param_key: "${TILE5_TAP_PARAM_KEY}"
param_val: "${TILE5_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile5).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE5_LONGPRESS}";
std::string type = "${TILE5_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE5_TITLE}"
entity: "${TILE5_ENTITY}"
tile_type: "${TILE5_TYPE}"
longpress_mode: "${TILE5_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile5).state;"
off_value: !lambda "return atoi(\"${TILE5_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile5_brightness).state;"
percentage_value: !lambda "return id(tile5_percentage).state;"
icon_text: "${TILE5_ICON}"
slider_bg_color: ${TILE5_BG_DISABLED_COLOR}
slider_fill_color: ${TILE5_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE5_ICON_ACTIVE_COLOR}
# ---------- TILE 6 ----------
- obj:
id: tile6
x: 164
y: 174
width: 147
height: 52
styles: style_tile
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- obj:
id: tile6_icon_circle
x: 0
y: 0
width: 36
height: 36
styles: style_icon_circle
clickable: false
scrollable: false
scrollbar_mode: 'OFF'
widgets:
- label:
id: tile6_icon_lbl
align: CENTER
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE6_ICON}"
clickable: false
- label:
id: t6_title
x: 48
y: 4
text: "${TILE6_TITLE}"
styles: style_title
clickable: false
- label:
id: t6_value
x: 48
y: 18
text: "—"
styles: style_value
clickable: false
on_short_click:
- script.execute: { id: publish_action, action: "tile6_press" }
- script.execute:
id: do_tile_action
tile_type: "${TILE6_TYPE}"
tap_action: "${TILE6_TAP_ACTION}"
service: "${TILE6_TAP_SERVICE}"
entity_id: "${TILE6_ENTITY}"
param_key: "${TILE6_TAP_PARAM_KEY}"
param_val: "${TILE6_TAP_PARAM_VAL}"
was_on: !lambda "return id(ha_state_tile6).state;"
on_long_press:
- if:
condition:
lambda: |-
std::string lp = "${TILE6_LONGPRESS}";
std::string type = "${TILE6_TYPE}";
if (lp == "none") return false;
if (lp == "auto") return (type == "light" || type == "fan");
return (lp == "brightness" || lp == "percentage");
then:
- script.execute:
id: open_value_overlay
title: "${TILE6_TITLE}"
entity: "${TILE6_ENTITY}"
tile_type: "${TILE6_TYPE}"
longpress_mode: "${TILE6_LONGPRESS}"
was_on: !lambda "return id(ha_state_tile6).state;"
off_value: !lambda "return atoi(\"${TILE6_LONGPRESS_OFF_VALUE}\");"
brightness_value: !lambda "return id(tile6_brightness).state;"
percentage_value: !lambda "return id(tile6_percentage).state;"
icon_text: "${TILE6_ICON}"
slider_bg_color: ${TILE6_BG_DISABLED_COLOR}
slider_fill_color: ${TILE6_CIRCLE_ACTIVE_COLOR}
slider_icon_color: ${TILE6_ICON_ACTIVE_COLOR}
# ---------- VALUE SLIDER OVERLAY ----------
- obj:
id: brightness_overlay
x: 0
y: 0
width: 320
height: 240
bg_opa: TRANSP
hidden: true
scrollable: false
scrollbar_mode: 'OFF'
pad_left: 0
pad_right: 0
pad_top: 0
pad_bottom: 0
border_width: 0
widgets:
- obj:
id: brightness_overlay_bg
x: 0
y: 0
width: 320
height: 240
bg_color: 0x1a1a2e
bg_opa: COVER
border_width: 0
radius: 0
clickable: true
scrollable: false
on_click:
- lvgl.widget.hide: brightness_overlay
- obj:
id: brightness_overlay_dim
x: 0
y: 0
width: 320
height: 240
bg_color: 0x000000
bg_opa: 18%
border_width: 0
clickable: false
scrollable: false
- label:
id: overlay_title
align: TOP_MID
y: 10
text: "Light"
styles: style_room
- label:
id: overlay_value
align: TOP_MID
y: 35
text: "100 %"
styles: style_value_big
- slider:
id: overlay_slider
align: CENTER
y: 18
width: 96
height: 160
min_value: 0
max_value: 100
value: 100
adv_hittest: false
bg_color: 0x939391
bg_opa: 100%
radius: 28
border_width: 0
indicator:
bg_color: 0xFEC600
bg_opa: 100%
radius: 28
knob:
bg_opa: 0%
border_width: 0
shadow_width: 0
pad_all: 10
on_value:
- script.execute:
id: slider_preview
value: !lambda "return x;"
on_release:
- script.execute:
id: slider_commit
value: !lambda "return lv_slider_get_value(id(overlay_slider));"
widgets:
- label:
id: overlay_icon
align: BOTTOM_MID
y: -10
text_font: materialdesign_icons
text_color: 0xFFFFFF
text: "${TILE1_ICON}"
clickable: false
script:
- id: publish_action
mode: queued
parameters:
action: string
then:
- text_sensor.template.publish:
id: smartdisplay_action
state: !lambda 'return action;'
- delay: 200ms
- text_sensor.template.publish:
id: smartdisplay_action
state: ""
- id: slider_preview
parameters:
value: int
then:
- lambda: |-
char buf[20];
snprintf(buf, sizeof(buf), "%d%s", value, id(active_value_suffix).c_str());
lv_label_set_text(id(overlay_value), buf);
- id: slider_commit
parameters:
value: int
then:
- if:
condition:
lambda: "return id(active_control_kind) == \"light_brightness\";"
then:
- homeassistant.action:
action: light.turn_on
data:
entity_id: !lambda "return id(active_entity);"
brightness_pct: !lambda "return value;"
else:
- if:
condition:
lambda: "return id(active_control_kind) == \"fan_percentage\";"
then:
- if:
condition:
lambda: "return value <= 0;"
then:
- homeassistant.action:
action: fan.turn_off
data:
entity_id: !lambda "return id(active_entity);"
else:
- homeassistant.action:
action: fan.turn_on
data:
entity_id: !lambda "return id(active_entity);"
- delay: 150ms
- homeassistant.action:
action: fan.set_percentage
data:
entity_id: !lambda "return id(active_entity);"
percentage: !lambda "return value;"
- id: do_tile_action
mode: queued
parameters:
tile_type: string
tap_action: string
service: string
entity_id: string
param_key: string
param_val: string
was_on: bool
then:
- if:
condition:
lambda: 'return std::string("${DIRECT_ACTIONS}") == "true";'
then:
- lambda: |-
ESP_LOGD("tile", "do_tile_action type=%s action=%s service=%s entity=%s key=%s val=%s was_on=%d",
tile_type.c_str(), tap_action.c_str(), service.c_str(), entity_id.c_str(),
param_key.c_str(), param_val.c_str(), (int)was_on);
- if:
condition:
lambda: "return tap_action == \"fan_toggle_preset\";"
then:
- if:
condition:
lambda: "return was_on;"
then:
- homeassistant.action:
action: fan.turn_off
data:
entity_id: !lambda 'return entity_id;'
else:
- homeassistant.action:
action: fan.turn_on
data:
entity_id: !lambda 'return entity_id;'
- delay: 150ms
- homeassistant.action:
action: fan.set_preset_mode
data:
entity_id: !lambda 'return entity_id;'
preset_mode: !lambda 'return param_val;'
else:
- if:
condition:
lambda: |-
std::string r = tap_action;
if (r == "auto") r = (tile_type == "scene" || tile_type == "script") ? "activate" : "toggle";
return r == "toggle";
then:
- if:
condition:
lambda: "return service.size() > 0;"
then:
- homeassistant.action:
action: !lambda 'return service;'
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "light";'
then:
- homeassistant.action:
action: light.toggle
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "fan";'
then:
- homeassistant.action:
action: fan.toggle
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "switch";'
then:
- homeassistant.action:
action: switch.toggle
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: |-
std::string r = tap_action;
if (r == "auto") r = (tile_type == "scene" || tile_type == "script") ? "activate" : "toggle";
return r == "activate";
then:
- if:
condition:
lambda: "return service.size() > 0;"
then:
- if:
condition:
lambda: 'return param_key == "preset_mode";'
then:
- homeassistant.action:
action: !lambda 'return service;'
data:
entity_id: !lambda 'return entity_id;'
preset_mode: !lambda 'return param_val;'
else:
- if:
condition:
lambda: 'return param_key == "brightness_pct";'
then:
- homeassistant.action:
action: !lambda 'return service;'
data:
entity_id: !lambda 'return entity_id;'
brightness_pct: !lambda 'return atoi(param_val.c_str());'
else:
- if:
condition:
lambda: 'return param_key == "percentage";'
then:
- homeassistant.action:
action: !lambda 'return service;'
data:
entity_id: !lambda 'return entity_id;'
percentage: !lambda 'return atoi(param_val.c_str());'
else:
- homeassistant.action:
action: !lambda 'return service;'
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "scene";'
then:
- homeassistant.action:
action: scene.turn_on
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "script";'
then:
- homeassistant.action:
action: script.turn_on
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "light";'
then:
- homeassistant.action:
action: light.turn_on
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "fan";'
then:
- homeassistant.action:
action: fan.turn_on
data:
entity_id: !lambda 'return entity_id;'
else:
- if:
condition:
lambda: 'return tile_type == "switch";'
then:
- homeassistant.action:
action: switch.turn_on
data:
entity_id: !lambda 'return entity_id;'
- id: open_value_overlay
parameters:
title: string
entity: string
tile_type: string
longpress_mode: string
was_on: bool
off_value: int
brightness_value: float
percentage_value: float
icon_text: string
slider_bg_color: uint32_t
slider_fill_color: uint32_t
slider_icon_color: uint32_t
then:
- lambda: |-
std::string mode = longpress_mode;
if (mode == "auto") {
if (tile_type == "light") mode = "brightness";
else if (tile_type == "fan") mode = "percentage";
else mode = "none";
}
if (mode == "none") return;
id(active_entity) = entity;
id(active_value_suffix) = " %";
id(overlay_slider_bg_color) = slider_bg_color;
id(overlay_slider_fill_color) = slider_fill_color;
int pct = off_value;
if (mode == "brightness") {
id(active_control_kind) = "light_brightness";
if (was_on) {
if (isnan(brightness_value)) pct = 100;
else pct = (int) lround((brightness_value / 255.0f) * 100.0f);
}
} else if (mode == "percentage") {
id(active_control_kind) = "fan_percentage";
if (was_on) {
if (isnan(percentage_value)) pct = 0;
else pct = (int) lround(percentage_value);
}
} else { return; }
if (pct < 0) pct = 0;
if (pct > 100) pct = 100;
lv_label_set_text(id(overlay_title), title.c_str());
lv_label_set_text(id(overlay_icon), icon_text.c_str());
lv_slider_set_value(id(overlay_slider), pct, LV_ANIM_OFF);
char buf[20];
snprintf(buf, sizeof(buf), "%d%s", pct, id(active_value_suffix).c_str());
lv_label_set_text(id(overlay_value), buf);
lv_obj_set_style_bg_color(id(overlay_slider), lv_color_hex(slider_bg_color), LV_PART_MAIN);
lv_obj_set_style_bg_opa(id(overlay_slider), LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(id(overlay_slider), lv_color_hex(slider_fill_color), LV_PART_INDICATOR);
lv_obj_set_style_bg_opa(id(overlay_slider), LV_OPA_COVER, LV_PART_INDICATOR);
lv_obj_set_style_text_color(id(overlay_icon), lv_color_hex(slider_icon_color), 0);
- lvgl.widget.show: brightness_overlay
- id: ui_refresh
mode: queued
then:
- lambda: |-
auto set_lbl = [](lv_obj_t* lbl, const std::string& s) {
if (lbl) lv_label_set_text(lbl, s.c_str());
};
auto set_value_auto = [&](lv_obj_t* lbl, bool on,
const std::string& tile_type, const std::string& value_mode,
float brightness, float percentage, const std::string& preset,
const std::string& label_on, const std::string& label_off) {
std::string mode = value_mode;
if (mode == "auto" || mode.empty()) {
if (tile_type == "light") mode = "brightness";
else if (tile_type == "fan") mode = preset.empty() ? "percentage" : "preset";
else mode = "text";
}
if (mode == "brightness") {
if (!on) { set_lbl(lbl, label_off); return; }
if (isnan(brightness)) { set_lbl(lbl, "100 %"); return; }
int pct = (int) lround((brightness / 255.0f) * 100.0f);
char buf[8]; snprintf(buf, sizeof(buf), "%d %%", pct);
set_lbl(lbl, std::string(buf)); return;
}
if (mode == "percentage") {
if (!on) { set_lbl(lbl, label_off); return; }
int pct = isnan(percentage) ? 0 : (int) lround(percentage);
char buf[8]; snprintf(buf, sizeof(buf), "%d %%", pct);
set_lbl(lbl, std::string(buf)); return;
}
if (mode == "preset") {
if (!on) { set_lbl(lbl, label_off); return; }
set_lbl(lbl, !preset.empty() ? preset : label_on); return;
}
if (mode == "text") {
if (tile_type == "scene" || tile_type == "script") set_lbl(lbl, label_on);
else set_lbl(lbl, on ? label_on : label_off);
return;
}
set_lbl(lbl, "—");
};
set_value_auto(id(t1_value), id(ha_state_tile1).state, "${TILE1_TYPE}", "${TILE1_VALUE_MODE}",
id(tile1_brightness).state, id(tile1_percentage).state, std::string(id(tile1_preset).state.c_str()),
"${TILE1_LABEL_ON}", "${TILE1_LABEL_OFF}");
set_value_auto(id(t2_value), id(ha_state_tile2).state, "${TILE2_TYPE}", "${TILE2_VALUE_MODE}",
id(tile2_brightness).state, id(tile2_percentage).state, std::string(id(tile2_preset).state.c_str()),
"${TILE2_LABEL_ON}", "${TILE2_LABEL_OFF}");
set_value_auto(id(t3_value), id(ha_state_tile3).state, "${TILE3_TYPE}", "${TILE3_VALUE_MODE}",
id(tile3_brightness).state, id(tile3_percentage).state, std::string(id(tile3_preset).state.c_str()),
"${TILE3_LABEL_ON}", "${TILE3_LABEL_OFF}");
set_value_auto(id(t4_value), id(ha_state_tile4).state, "${TILE4_TYPE}", "${TILE4_VALUE_MODE}",
id(tile4_brightness).state, id(tile4_percentage).state, std::string(id(tile4_preset).state.c_str()),
"${TILE4_LABEL_ON}", "${TILE4_LABEL_OFF}");
set_value_auto(id(t5_value), id(ha_state_tile5).state, "${TILE5_TYPE}", "${TILE5_VALUE_MODE}",
id(tile5_brightness).state, id(tile5_percentage).state, std::string(id(tile5_preset).state.c_str()),
"${TILE5_LABEL_ON}", "${TILE5_LABEL_OFF}");
set_value_auto(id(t6_value), id(ha_state_tile6).state, "${TILE6_TYPE}", "${TILE6_VALUE_MODE}",
id(tile6_brightness).state, id(tile6_percentage).state, std::string(id(tile6_preset).state.c_str()),
"${TILE6_LABEL_ON}", "${TILE6_LABEL_OFF}");
{
auto now = id(homeassistant_time).now();
char buf[10];
if (std::string("${TIME_24H}") == "true") {
snprintf(buf, sizeof(buf), "%02d:%02d", now.hour, now.minute);
} else {
int h = now.hour % 12; if (h == 0) h = 12;
snprintf(buf, sizeof(buf), "%d:%02d %s", h, now.minute, now.hour >= 12 ? "PM" : "AM");
}
set_lbl(id(lbl_time), std::string(buf));
}
auto apply_tile = [&](bool active, lv_obj_t* tile, lv_obj_t* circle,
lv_obj_t* title, lv_obj_t* value, lv_obj_t* icon_lbl,
uint32_t ca, uint32_t cd, uint32_t ia, uint32_t id_,
uint32_t ba, uint32_t bd, uint32_t ta, uint32_t td,
uint32_t va, uint32_t vd) {
lv_obj_set_style_bg_color(tile, lv_color_hex(active ? ba : bd), 0);
lv_obj_set_style_bg_color(circle, lv_color_hex(active ? ca : cd), 0);
lv_obj_set_style_text_color(icon_lbl, lv_color_hex(active ? ia : id_), 0);
lv_obj_set_style_text_color(title, lv_color_hex(active ? ta : td), 0);
lv_obj_set_style_text_color(value, lv_color_hex(active ? va : vd), 0);
};
apply_tile(id(ha_state_tile1).state, id(tile1), id(tile1_icon_circle), id(t1_title), id(t1_value), id(tile1_icon_lbl),
${TILE1_CIRCLE_ACTIVE_COLOR}, ${TILE1_CIRCLE_DISABLED_COLOR}, ${TILE1_ICON_ACTIVE_COLOR}, ${TILE1_ICON_DISABLED_COLOR},
${TILE1_BG_ACTIVE_COLOR}, ${TILE1_BG_DISABLED_COLOR}, ${TILE1_TITLE_ACTIVE_COLOR}, ${TILE1_TITLE_DISABLED_COLOR},
${TILE1_VALUE_ACTIVE_COLOR}, ${TILE1_VALUE_DISABLED_COLOR});
apply_tile(id(ha_state_tile2).state, id(tile2), id(tile2_icon_circle), id(t2_title), id(t2_value), id(tile2_icon_lbl),
${TILE2_CIRCLE_ACTIVE_COLOR}, ${TILE2_CIRCLE_DISABLED_COLOR}, ${TILE2_ICON_ACTIVE_COLOR}, ${TILE2_ICON_DISABLED_COLOR},
${TILE2_BG_ACTIVE_COLOR}, ${TILE2_BG_DISABLED_COLOR}, ${TILE2_TITLE_ACTIVE_COLOR}, ${TILE2_TITLE_DISABLED_COLOR},
${TILE2_VALUE_ACTIVE_COLOR}, ${TILE2_VALUE_DISABLED_COLOR});
apply_tile(id(ha_state_tile3).state, id(tile3), id(tile3_icon_circle), id(t3_title), id(t3_value), id(tile3_icon_lbl),
${TILE3_CIRCLE_ACTIVE_COLOR}, ${TILE3_CIRCLE_DISABLED_COLOR}, ${TILE3_ICON_ACTIVE_COLOR}, ${TILE3_ICON_DISABLED_COLOR},
${TILE3_BG_ACTIVE_COLOR}, ${TILE3_BG_DISABLED_COLOR}, ${TILE3_TITLE_ACTIVE_COLOR}, ${TILE3_TITLE_DISABLED_COLOR},
${TILE3_VALUE_ACTIVE_COLOR}, ${TILE3_VALUE_DISABLED_COLOR});
apply_tile(id(ha_state_tile4).state, id(tile4), id(tile4_icon_circle), id(t4_title), id(t4_value), id(tile4_icon_lbl),
${TILE4_CIRCLE_ACTIVE_COLOR}, ${TILE4_CIRCLE_DISABLED_COLOR}, ${TILE4_ICON_ACTIVE_COLOR}, ${TILE4_ICON_DISABLED_COLOR},
${TILE4_BG_ACTIVE_COLOR}, ${TILE4_BG_DISABLED_COLOR}, ${TILE4_TITLE_ACTIVE_COLOR}, ${TILE4_TITLE_DISABLED_COLOR},
${TILE4_VALUE_ACTIVE_COLOR}, ${TILE4_VALUE_DISABLED_COLOR});
apply_tile(id(ha_state_tile5).state, id(tile5), id(tile5_icon_circle), id(t5_title), id(t5_value), id(tile5_icon_lbl),
${TILE5_CIRCLE_ACTIVE_COLOR}, ${TILE5_CIRCLE_DISABLED_COLOR}, ${TILE5_ICON_ACTIVE_COLOR}, ${TILE5_ICON_DISABLED_COLOR},
${TILE5_BG_ACTIVE_COLOR}, ${TILE5_BG_DISABLED_COLOR}, ${TILE5_TITLE_ACTIVE_COLOR}, ${TILE5_TITLE_DISABLED_COLOR},
${TILE5_VALUE_ACTIVE_COLOR}, ${TILE5_VALUE_DISABLED_COLOR});
apply_tile(id(ha_state_tile6).state, id(tile6), id(tile6_icon_circle), id(t6_title), id(t6_value), id(tile6_icon_lbl),
${TILE6_CIRCLE_ACTIVE_COLOR}, ${TILE6_CIRCLE_DISABLED_COLOR}, ${TILE6_ICON_ACTIVE_COLOR}, ${TILE6_ICON_DISABLED_COLOR},
${TILE6_BG_ACTIVE_COLOR}, ${TILE6_BG_DISABLED_COLOR}, ${TILE6_TITLE_ACTIVE_COLOR}, ${TILE6_TITLE_DISABLED_COLOR},
${TILE6_VALUE_ACTIVE_COLOR}, ${TILE6_VALUE_DISABLED_COLOR});
- component.update: my_display