Give a lamp's modes a page: the effects, palettes, presets, speed and intensity of a WLED behind its colour card, with a drum picker and the effect's name on the tile (0.2.83)
A light that offers effects gets a sparkles key at the top right of its colour card. It opens a page with a row per thing the lamp offers, all from Home Assistant: the light's effect and the select entities of its device (a WLED's colour palette, preset and playlist) with what they are set to, and a slider per number entity of the device (speed, intensity). Names are Home Assistant's own English entity translations, icons its frontend's; nothing about a brand is hardcoded beyond a preferred order of translation keys. A row opens LVGL's roller with every name Home Assistant lists at that moment, asked for when the picker opens (esphome.screen_options, answered with op: options, one page of names per message), the effects alphabetically with Solid on top. The check key at the top right sends the choice as one action; the back key sends nothing. A slider sends number.set_value when let go. While an effect runs, the tile names it instead of the brightness. Firmware 0.2.70: effects_page.h (built when it opens, gone when it closes), Extra.effect/option_rows/number_rows, options_request, a hidden roller widget so ESPHome compiles LVGL's roller, five firmware-only glyphs. App 0.2.83: light_effects.py, the effect attribute, the device rows in the state message, card_options_loop. Checked on the host with a virtual finger (35/35 on both boards) and compiled for both ESP32 boards; CYD 1,675,424 B (91.3 %). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+62
-1
@@ -17,7 +17,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.69"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.70"
|
||||
# A tap survives a finger that drifts up to this far (320 px over 58 mm: 1 cm); further is a swipe.
|
||||
TOUCH_MOVE_LIMIT_PX: "56"
|
||||
# Shortest contact that counts as a tap; a resistive panel bounces, a capacitive one does not.
|
||||
@@ -314,6 +314,7 @@ esphome:
|
||||
theme::set_dark(settings_screen::dark_mode != 0);
|
||||
runtime_tiles::settings_changed = []() { id(apply_screen_settings).execute(); };
|
||||
runtime_tiles::dismiss = []() {
|
||||
effects_page::close();
|
||||
runtime_tiles::hide_detail();
|
||||
id(active_entity).clear();
|
||||
lv_obj_add_flag(id(brightness_overlay), LV_OBJ_FLAG_HIDDEN);
|
||||
@@ -363,6 +364,7 @@ esphome:
|
||||
std::to_string(t.minimum), std::to_string(t.maximum), std::to_string(t.step));
|
||||
};
|
||||
runtime_tiles::detail_update = [](runtime_tiles::Tile &t) {
|
||||
effects_page::updated(t);
|
||||
if (id(active_entity) != t.entity || id(touch_down)) return;
|
||||
if (t.domain() == "climate" && !lv_obj_has_flag(id(climate_detail_overlay), LV_OBJ_FLAG_HIDDEN)) {
|
||||
if (id(climate_edit_pending) && millis() - id(climate_edit_ms) < 3000) return;
|
||||
@@ -386,6 +388,24 @@ esphome:
|
||||
light_controls::commits[0] = [](int value) { id(set_light_hue).execute(value); };
|
||||
light_controls::commits[1] = [](int value) { id(set_light_color_temperature).execute(value); };
|
||||
light_controls::commits[2] = [](int value) { id(color_brightness_commit).execute(value); };
|
||||
// The effects page behind the colour card's sparkles key (firmware 0.2.70+): fonts, the tile it shows, and
|
||||
// the ways out: actions to Home Assistant and the question for a picker's names.
|
||||
effects_page::title_font = id(headline)->get_lv_font();
|
||||
effects_page::row_font = id(sublabel_big)->get_lv_font();
|
||||
effects_page::roller_font = id(sublabel_big)->get_lv_font();
|
||||
effects_page::icon_font = id(materialdesign_icons_mini)->get_lv_font();
|
||||
effects_page::tile_of = [](const std::string &entity) -> const runtime_tiles::Tile * {
|
||||
for (size_t i = 0; i < runtime_tiles::model.count; ++i) if (runtime_tiles::model.tiles[i].entity == entity) return &runtime_tiles::model.tiles[i];
|
||||
return nullptr;
|
||||
};
|
||||
effects_page::send = [](const std::string &service, const std::string &entity, const std::string &key, const std::string &value) {
|
||||
runtime_tiles::action(service, entity, key, value);
|
||||
};
|
||||
effects_page::ask = [](const std::string &entity, unsigned page) { runtime_tiles::options_request(entity, page); };
|
||||
effects_page::drift = []() { return cyd::touch_guard.distance(); };
|
||||
effects_page::tap_limit = ${TOUCH_MOVE_LIMIT_PX};
|
||||
effects_page::now = []() { return (uint32_t) millis(); };
|
||||
runtime_tiles::options_received = effects_page::received;
|
||||
- lambda: |-
|
||||
if (!runtime_tiles::enabled) return;
|
||||
screen_calibration::apply = [](const screen_calibration::Calibration &cal) {
|
||||
@@ -423,6 +443,7 @@ esphome:
|
||||
theme::redraw = []() {
|
||||
runtime_tiles::restyle();
|
||||
light_controls::restyle();
|
||||
effects_page::restyle();
|
||||
settings_screen::restyle();
|
||||
if (id(alert_active)) lv_obj_set_style_bg_color(id(alert_card), lv_color_hex(theme::surface(id(alert_card_color))), LV_PART_MAIN);
|
||||
if (!lv_obj_has_flag(id(climate_detail_overlay), LV_OBJ_FLAG_HIDDEN)) id(climate_card_refresh).execute();
|
||||
@@ -1231,6 +1252,11 @@ font:
|
||||
- "\U000F1B73" # speaker-pause
|
||||
- "\U000F1B72" # speaker-play
|
||||
- "\U000F04C5" # speedometer
|
||||
- "\U000F0674" # creation
|
||||
- "\U000F0E0C" # palette-outline
|
||||
- "\U000F0411" # playlist-play
|
||||
- "\U000F08FF" # play-speed
|
||||
- "\U000F00DF" # brightness-6
|
||||
- "\U000F1429" # spoon-sugar
|
||||
- "\U000F0E67" # sprout-outline
|
||||
- "\U000F0764" # square
|
||||
@@ -1879,6 +1905,14 @@ lvgl:
|
||||
height: 2
|
||||
spin_time: 1s
|
||||
arc_length: 60deg
|
||||
# Never shown either: it makes ESPHome compile LVGL's roller, the drum a light's effects page picks from
|
||||
# (firmware 0.2.70+).
|
||||
- roller:
|
||||
id: roller_seed
|
||||
hidden: true
|
||||
width: 2
|
||||
height: 2
|
||||
options: ["-"]
|
||||
- label:
|
||||
id: lbl_room
|
||||
x: 11
|
||||
@@ -2849,6 +2883,31 @@ lvgl:
|
||||
text_font: materialdesign_icons_mini
|
||||
clickable: false
|
||||
|
||||
# The sparkles key (firmware 0.2.70+): a light with effects, or with modes on its device (a WLED's palette,
|
||||
# preset, speed), opens its effects page. Hidden for every other light.
|
||||
- obj:
|
||||
id: color_effects_button
|
||||
align: TOP_RIGHT
|
||||
x: -10
|
||||
y: 8
|
||||
width: 40
|
||||
height: 40
|
||||
radius: 999
|
||||
styles: paint_key
|
||||
bg_opa: COVER
|
||||
border_width: 0
|
||||
hidden: true
|
||||
clickable: true
|
||||
scrollable: false
|
||||
on_click:
|
||||
- lambda: 'effects_page::open(id(active_entity));'
|
||||
widgets:
|
||||
- label:
|
||||
align: CENTER
|
||||
text: "\U000F0674"
|
||||
text_font: materialdesign_icons_mini
|
||||
clickable: false
|
||||
|
||||
- label:
|
||||
id: color_detail_title
|
||||
width: 210
|
||||
@@ -4318,6 +4377,8 @@ script:
|
||||
- lambda: |-
|
||||
lv_label_set_text(id(color_detail_title), id(active_title).c_str());
|
||||
light_controls::open(id(active_entity), id(active_supports_color), id(active_supports_temperature), id(active_brightness_pct));
|
||||
if (effects_page::offered(id(active_entity))) lv_obj_remove_flag(id(color_effects_button), LV_OBJ_FLAG_HIDDEN);
|
||||
else lv_obj_add_flag(id(color_effects_button), LV_OBJ_FLAG_HIDDEN);
|
||||
- lvgl.widget.hide: brightness_overlay
|
||||
- lvgl.widget.show: color_detail_overlay
|
||||
|
||||
|
||||
Reference in New Issue
Block a user