Show an alert from a Home Assistant automation (0.2.36)
Every screen gets the user action esphome.<device>_show_alert with title, subtitle, icon, color, button_text, timeout and flash. The card sits on LVGL's top layer above every page, card and the dim overlay, wakes the screen and keeps the backlight at its normal brightness until the button (or the timeout; 0 waits for the button, the button always closes at once). flash: true blinks the backlight four times on arrival. Icons are the tile picker names (also mdi:name or the hex codepoint of a compiled glyph, else alert-outline), colours the tile pastels. A new alert replaces the current one; every ending fires esphome.screen_alert with action, title and screen. dismiss_alert removes the card remotely. The field is button_text rather than button: ESPHome reserves the names of loaded components as ids and the CYD profile loads button:. The C++ namespace is screen_alert because the widget id alert_overlay becomes a global lv_obj_t*. tools/generate_icons.py now also writes tile_icon_names.h (name to codepoint) from the one icon list. Firmware 0.2.31 for both boards. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+272
-2
@@ -59,7 +59,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.30"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.31"
|
||||
# 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.
|
||||
@@ -636,6 +636,23 @@ substitutions:
|
||||
OVERLAY_SLIDER_W: "96"
|
||||
OVERLAY_SLIDER_H: "160"
|
||||
OVERLAY_ICON_Y: "74"
|
||||
|
||||
# Alert overlay (HA action show_alert), landscape 320x240: one card centred on LVGL's top layer.
|
||||
ALERT_CARD_W: "292"
|
||||
ALERT_CARD_H: "196"
|
||||
ALERT_ICON_X: "18"
|
||||
ALERT_ICON_Y: "16"
|
||||
ALERT_TEXT_X: "62"
|
||||
ALERT_TEXT_W: "212"
|
||||
ALERT_TITLE_Y: "16"
|
||||
ALERT_SUBTITLE_Y: "44"
|
||||
ALERT_SUBTITLE_H: "88"
|
||||
ALERT_BUTTON_W: "100"
|
||||
ALERT_BUTTON_H: "40"
|
||||
ALERT_BUTTON_INSET: "14"
|
||||
ALERT_TITLE_MAX: "48" # bytes; the label ends one line with an ellipsis
|
||||
ALERT_BUTTON_MAX: "12" # bytes on the Oké button
|
||||
ALERT_SUBTITLE_MAX: "160" # bytes; wraps over the rows the card has
|
||||
BG_TOP_COLOR: "0xE7E7E7" # lichte achtergrond, gelijk aan de Guition
|
||||
BG_BOTTOM_COLOR: "0xE7E7E7"
|
||||
TILE_ICON_X: "0"
|
||||
@@ -781,6 +798,7 @@ esphome:
|
||||
includes:
|
||||
- <esphome/components/smart_display/cyd_ui.h>
|
||||
- <esphome/components/smart_display/light_controls.h>
|
||||
- <esphome/components/smart_display/alert_overlay.h>
|
||||
name: ${DEVICE_NAME}
|
||||
friendly_name: ${DEVICE_FRIENDLY_NAME}
|
||||
on_boot:
|
||||
@@ -1028,6 +1046,32 @@ api:
|
||||
- action: ui_self_test
|
||||
then:
|
||||
- script.execute: ui_self_test
|
||||
# Home Assistant automations: esphome.<device>_show_alert puts a card over the whole
|
||||
# screen (README, "Alert vanuit een automatisering"); dismiss_alert removes it again.
|
||||
- action: show_alert
|
||||
variables:
|
||||
title: string
|
||||
subtitle: string
|
||||
icon: string
|
||||
color: string
|
||||
button_text: string
|
||||
timeout: int
|
||||
flash: bool
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_show
|
||||
title: !lambda 'return title;'
|
||||
subtitle: !lambda 'return subtitle;'
|
||||
icon: !lambda 'return icon;'
|
||||
color: !lambda 'return color;'
|
||||
button_text: !lambda 'return button_text;'
|
||||
timeout: !lambda 'return timeout;'
|
||||
flash: !lambda 'return flash;'
|
||||
- action: dismiss_alert
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "remote"
|
||||
|
||||
captive_portal:
|
||||
|
||||
@@ -1046,7 +1090,7 @@ interval:
|
||||
condition:
|
||||
lambda: |-
|
||||
if (!screen_settings::current.standby_enabled) return false;
|
||||
if (id(display_dimmed) || id(touch_down) || id(calibration_active)) return false;
|
||||
if (id(display_dimmed) || id(touch_down) || id(calibration_active) || id(alert_active)) return false;
|
||||
return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL);
|
||||
then:
|
||||
- script.execute: dim_display
|
||||
@@ -1068,6 +1112,18 @@ time:
|
||||
- lambda: 'if (!id(ui_refresh).is_running()) id(ui_refresh).execute();'
|
||||
|
||||
globals:
|
||||
# Alert overlay (HA action show_alert): standby waits while one is up.
|
||||
- id: alert_active
|
||||
type: bool
|
||||
initial_value: 'false'
|
||||
- id: alert_title_text
|
||||
type: std::string
|
||||
- id: alert_timeout_seconds
|
||||
type: int
|
||||
initial_value: '0'
|
||||
- id: alert_flash_requested
|
||||
type: bool
|
||||
initial_value: 'false'
|
||||
- id: rendered_frames
|
||||
type: uint32_t
|
||||
initial_value: '0'
|
||||
@@ -2193,6 +2249,111 @@ lvgl:
|
||||
text_color: 0x1B1B1B
|
||||
text_opa: 100%
|
||||
|
||||
# ---------- ALERT OVERLAY (HA action show_alert) ----------
|
||||
# LVGL's top layer sits above every page, card and the dim overlay; the card
|
||||
# is filled by the alert_show script. Fixed positions, no layout engine.
|
||||
top_layer:
|
||||
widgets:
|
||||
- obj:
|
||||
id: alert_overlay
|
||||
x: 0
|
||||
y: 0
|
||||
width: ${DISPLAY_W}
|
||||
height: ${DISPLAY_H}
|
||||
hidden: true
|
||||
bg_color: 0x101820
|
||||
bg_opa: 60%
|
||||
radius: 0
|
||||
border_width: 0
|
||||
pad_all: 0
|
||||
clickable: true
|
||||
scrollable: false
|
||||
scrollbar_mode: 'OFF'
|
||||
# Same look when pressed: a tap next to the card must not repaint the screen.
|
||||
pressed:
|
||||
bg_opa: 60%
|
||||
widgets:
|
||||
- obj:
|
||||
id: alert_card
|
||||
align: CENTER
|
||||
width: ${ALERT_CARD_W}
|
||||
height: ${ALERT_CARD_H}
|
||||
bg_color: 0xFFFFFF
|
||||
bg_opa: COVER
|
||||
radius: 18
|
||||
border_width: 1
|
||||
border_color: 0xDDDDDD
|
||||
border_opa: COVER
|
||||
shadow_width: 0
|
||||
pad_all: 0
|
||||
clickable: false
|
||||
scrollable: false
|
||||
scrollbar_mode: 'OFF'
|
||||
widgets:
|
||||
- label:
|
||||
id: alert_icon
|
||||
x: ${ALERT_ICON_X}
|
||||
y: ${ALERT_ICON_Y}
|
||||
text: "\U000F002A"
|
||||
text_font: materialdesign_icons
|
||||
text_color: 0x1B1B1B
|
||||
clickable: false
|
||||
- label:
|
||||
id: alert_title
|
||||
x: ${ALERT_TEXT_X}
|
||||
y: ${ALERT_TITLE_Y}
|
||||
width: ${ALERT_TEXT_W}
|
||||
long_mode: DOT
|
||||
text: "Melding"
|
||||
text_font: headline
|
||||
text_color: 0x1B1B1B
|
||||
clickable: false
|
||||
- label:
|
||||
id: alert_subtitle
|
||||
x: ${ALERT_TEXT_X}
|
||||
y: ${ALERT_SUBTITLE_Y}
|
||||
width: ${ALERT_TEXT_W}
|
||||
height: ${ALERT_SUBTITLE_H}
|
||||
long_mode: WRAP
|
||||
text: ""
|
||||
text_font: sublabel_big
|
||||
text_color: 0x3A3A3C
|
||||
clickable: false
|
||||
- obj:
|
||||
id: alert_ok
|
||||
align: BOTTOM_RIGHT
|
||||
x: -${ALERT_BUTTON_INSET}
|
||||
y: -${ALERT_BUTTON_INSET}
|
||||
width: ${ALERT_BUTTON_W}
|
||||
height: ${ALERT_BUTTON_H}
|
||||
radius: 999
|
||||
bg_color: 0x1B1B1B
|
||||
bg_opa: COVER
|
||||
border_width: 0
|
||||
shadow_width: 0
|
||||
pad_all: 0
|
||||
clickable: true
|
||||
scrollable: false
|
||||
pressed:
|
||||
bg_color: 0x3A3A3C
|
||||
bg_opa: COVER
|
||||
on_click:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return cyd::touch_guard.accept(millis(), 13);'
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "ok"
|
||||
widgets:
|
||||
- label:
|
||||
id: alert_ok_label
|
||||
align: CENTER
|
||||
text: "Oké"
|
||||
text_font: headline
|
||||
text_color: 0xFFFFFF
|
||||
clickable: false
|
||||
|
||||
pages:
|
||||
- id: home_page
|
||||
styles: style_bg_grad
|
||||
@@ -5030,6 +5191,9 @@ script:
|
||||
- lvgl.widget.show: vacuum_overlay
|
||||
- delay: 150ms
|
||||
- lvgl.widget.hide: vacuum_overlay
|
||||
- lvgl.widget.show: alert_overlay
|
||||
- delay: 150ms
|
||||
- lvgl.widget.hide: alert_overlay
|
||||
- lambda: 'if (!id(ui_refresh).is_running()) id(ui_refresh).execute();'
|
||||
- logger.log: "UI_TEST COMPLETE"
|
||||
|
||||
@@ -5100,6 +5264,112 @@ script:
|
||||
- lvgl.widget.hide: climate_mode_overlay
|
||||
- lvgl.widget.hide: vacuum_overlay
|
||||
|
||||
# ---------- ALERT (HA action show_alert) ----------
|
||||
# The screen wakes, keeps its normal brightness and shows the card until Oké or the
|
||||
# timeout (0: until Oké); the standby interval waits on alert_active. A new alert
|
||||
# replaces the current one; every ending reports itself as esphome.screen_alert.
|
||||
- id: alert_show
|
||||
mode: restart
|
||||
parameters:
|
||||
title: string
|
||||
subtitle: string
|
||||
icon: string
|
||||
color: string
|
||||
button_text: string
|
||||
timeout: int
|
||||
flash: bool
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(alert_active)) id(alert_report).execute("replaced");
|
||||
const auto alert = screen_alert::make(title, subtitle, icon, color, button_text, timeout, flash, ${ALERT_TITLE_MAX}, ${ALERT_SUBTITLE_MAX}, ${ALERT_BUTTON_MAX});
|
||||
id(alert_active) = true;
|
||||
id(alert_title_text) = alert.title;
|
||||
id(alert_timeout_seconds) = alert.timeout_seconds;
|
||||
id(alert_flash_requested) = alert.flash;
|
||||
lv_label_set_text(id(alert_icon), alert.icon.c_str());
|
||||
lv_label_set_text(id(alert_title), alert.title.c_str());
|
||||
lv_label_set_text(id(alert_subtitle), alert.subtitle.c_str());
|
||||
lv_label_set_text(id(alert_ok_label), alert.button.c_str());
|
||||
lv_obj_set_style_bg_color(id(alert_card), lv_color_hex(alert.color), LV_PART_MAIN);
|
||||
ESP_LOGI("alert", "show \"%s\" timeout=%d flash=%d", alert.title.c_str(), alert.timeout_seconds, (int) alert.flash);
|
||||
- script.execute: wake_display
|
||||
- lvgl.widget.show: alert_overlay
|
||||
- script.stop: alert_timeout
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_flash_requested);'
|
||||
then:
|
||||
- script.execute: alert_flash
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_timeout_seconds) > 0;'
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_timeout
|
||||
seconds: !lambda 'return id(alert_timeout_seconds);'
|
||||
|
||||
- id: alert_dismiss
|
||||
parameters:
|
||||
reason: string
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_active);'
|
||||
then:
|
||||
- lambda: |-
|
||||
id(alert_active) = false;
|
||||
id(last_touch_ms) = millis();
|
||||
ESP_LOGI("alert", "dismissed: %s", reason.c_str());
|
||||
- lvgl.widget.hide: alert_overlay
|
||||
- script.stop: alert_timeout
|
||||
- script.stop: alert_flash
|
||||
- light.turn_on:
|
||||
id: back_light
|
||||
transition_length: 80ms
|
||||
brightness: !lambda "return screen_settings::current.brightness / 100.0f;"
|
||||
- script.execute:
|
||||
id: alert_report
|
||||
action: !lambda 'return reason;'
|
||||
|
||||
# Four backlight blinks when the alert arrives; the screen then stays on as usual.
|
||||
- id: alert_flash
|
||||
mode: restart
|
||||
then:
|
||||
- repeat:
|
||||
count: 4
|
||||
then:
|
||||
- light.turn_off:
|
||||
id: back_light
|
||||
transition_length: 0s
|
||||
- delay: 120ms
|
||||
- light.turn_on:
|
||||
id: back_light
|
||||
transition_length: 0s
|
||||
brightness: !lambda "return screen_settings::current.brightness / 100.0f;"
|
||||
- delay: 170ms
|
||||
|
||||
- id: alert_timeout
|
||||
mode: restart
|
||||
parameters:
|
||||
seconds: int
|
||||
then:
|
||||
- delay: !lambda 'return static_cast<uint32_t>(seconds) * 1000UL;'
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "timeout"
|
||||
|
||||
# Home Assistant adds device_id; action is ok, timeout, replaced or remote.
|
||||
- id: alert_report
|
||||
parameters:
|
||||
action: string
|
||||
then:
|
||||
- homeassistant.event:
|
||||
event: esphome.screen_alert
|
||||
data:
|
||||
action: !lambda 'return action;'
|
||||
title: !lambda 'return id(alert_title_text);'
|
||||
screen: !lambda 'return App.get_name();'
|
||||
|
||||
- id: wake_display
|
||||
mode: restart
|
||||
then:
|
||||
|
||||
+264
-2
@@ -2,7 +2,7 @@
|
||||
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
|
||||
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.30"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.31"
|
||||
# 0: no drift limit; LVGL decides, releasing inside the tile is a tap, leaving it is not
|
||||
# (like iOS). The CYD keeps a limit because its resistive panel jumps.
|
||||
TOUCH_MOVE_LIMIT_PX: "0"
|
||||
@@ -550,6 +550,23 @@ substitutions:
|
||||
TILE_W: "218"
|
||||
TILE_H: "108"
|
||||
HEADER_Y: "22"
|
||||
|
||||
# Alert overlay (HA action show_alert), 480x480: one card centred on LVGL's top layer.
|
||||
ALERT_CARD_W: "420"
|
||||
ALERT_CARD_H: "320"
|
||||
ALERT_ICON_X: "26"
|
||||
ALERT_ICON_Y: "22"
|
||||
ALERT_TEXT_X: "90"
|
||||
ALERT_TEXT_W: "304"
|
||||
ALERT_TITLE_Y: "26"
|
||||
ALERT_SUBTITLE_Y: "68"
|
||||
ALERT_SUBTITLE_H: "150"
|
||||
ALERT_BUTTON_W: "150"
|
||||
ALERT_BUTTON_H: "60"
|
||||
ALERT_BUTTON_INSET: "22"
|
||||
ALERT_TITLE_MAX: "64" # bytes; the label ends one line with an ellipsis
|
||||
ALERT_BUTTON_MAX: "16" # bytes on the Oké button
|
||||
ALERT_SUBTITLE_MAX: "240" # bytes; wraps over the rows the card has
|
||||
OVERLAY_SLIDER_W: "144"
|
||||
OVERLAY_SLIDER_H: "300"
|
||||
OVERLAY_ICON_Y: "148"
|
||||
@@ -594,6 +611,7 @@ esphome:
|
||||
- <esphome/components/smart_display/light_controls.h>
|
||||
- <esphome/components/smart_display/guition_diagnostics.h>
|
||||
- <esphome/components/smart_display/backlight_fade.h>
|
||||
- <esphome/components/smart_display/alert_overlay.h>
|
||||
name: ${DEVICE_NAME}
|
||||
friendly_name: ${DEVICE_FRIENDLY_NAME}
|
||||
on_boot:
|
||||
@@ -833,6 +851,32 @@ api:
|
||||
- action: ui_self_test
|
||||
then:
|
||||
- script.execute: ui_self_test
|
||||
# Home Assistant automations: esphome.<device>_show_alert puts a card over the whole
|
||||
# screen (README, "Alert vanuit een automatisering"); dismiss_alert removes it again.
|
||||
- action: show_alert
|
||||
variables:
|
||||
title: string
|
||||
subtitle: string
|
||||
icon: string
|
||||
color: string
|
||||
button_text: string
|
||||
timeout: int
|
||||
flash: bool
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_show
|
||||
title: !lambda 'return title;'
|
||||
subtitle: !lambda 'return subtitle;'
|
||||
icon: !lambda 'return icon;'
|
||||
color: !lambda 'return color;'
|
||||
button_text: !lambda 'return button_text;'
|
||||
timeout: !lambda 'return timeout;'
|
||||
flash: !lambda 'return flash;'
|
||||
- action: dismiss_alert
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "remote"
|
||||
|
||||
captive_portal:
|
||||
|
||||
@@ -851,7 +895,7 @@ interval:
|
||||
condition:
|
||||
lambda: |-
|
||||
if (!screen_settings::current.standby_enabled) return false;
|
||||
if (id(display_dimmed) || id(touch_down) || id(calibration_active)) return false;
|
||||
if (id(display_dimmed) || id(touch_down) || id(calibration_active) || id(alert_active)) return false;
|
||||
return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL);
|
||||
then:
|
||||
- script.execute: dim_display
|
||||
@@ -873,6 +917,18 @@ time:
|
||||
- lambda: 'if (!id(ui_refresh).is_running()) id(ui_refresh).execute();'
|
||||
|
||||
globals:
|
||||
# Alert overlay (HA action show_alert): standby waits while one is up.
|
||||
- id: alert_active
|
||||
type: bool
|
||||
initial_value: 'false'
|
||||
- id: alert_title_text
|
||||
type: std::string
|
||||
- id: alert_timeout_seconds
|
||||
type: int
|
||||
initial_value: '0'
|
||||
- id: alert_flash_requested
|
||||
type: bool
|
||||
initial_value: 'false'
|
||||
- id: rendered_frames
|
||||
type: uint32_t
|
||||
initial_value: '0'
|
||||
@@ -2013,6 +2069,111 @@ lvgl:
|
||||
text_color: 0x1B1B1B
|
||||
text_opa: 100%
|
||||
|
||||
# ---------- ALERT OVERLAY (HA action show_alert) ----------
|
||||
# LVGL's top layer sits above every page, card and the dim overlay; the card
|
||||
# is filled by the alert_show script. Fixed positions, no layout engine.
|
||||
top_layer:
|
||||
widgets:
|
||||
- obj:
|
||||
id: alert_overlay
|
||||
x: 0
|
||||
y: 0
|
||||
width: ${DISPLAY_W}
|
||||
height: ${DISPLAY_H}
|
||||
hidden: true
|
||||
bg_color: 0x101820
|
||||
bg_opa: 60%
|
||||
radius: 0
|
||||
border_width: 0
|
||||
pad_all: 0
|
||||
clickable: true
|
||||
scrollable: false
|
||||
scrollbar_mode: 'OFF'
|
||||
# Same look when pressed: a tap next to the card must not repaint the screen.
|
||||
pressed:
|
||||
bg_opa: 60%
|
||||
widgets:
|
||||
- obj:
|
||||
id: alert_card
|
||||
align: CENTER
|
||||
width: ${ALERT_CARD_W}
|
||||
height: ${ALERT_CARD_H}
|
||||
bg_color: 0xFFFFFF
|
||||
bg_opa: COVER
|
||||
radius: 18
|
||||
border_width: 1
|
||||
border_color: 0xDDDDDD
|
||||
border_opa: COVER
|
||||
shadow_width: 0
|
||||
pad_all: 0
|
||||
clickable: false
|
||||
scrollable: false
|
||||
scrollbar_mode: 'OFF'
|
||||
widgets:
|
||||
- label:
|
||||
id: alert_icon
|
||||
x: ${ALERT_ICON_X}
|
||||
y: ${ALERT_ICON_Y}
|
||||
text: "\U000F002A"
|
||||
text_font: materialdesign_icons
|
||||
text_color: 0x1B1B1B
|
||||
clickable: false
|
||||
- label:
|
||||
id: alert_title
|
||||
x: ${ALERT_TEXT_X}
|
||||
y: ${ALERT_TITLE_Y}
|
||||
width: ${ALERT_TEXT_W}
|
||||
long_mode: DOT
|
||||
text: "Melding"
|
||||
text_font: headline
|
||||
text_color: 0x1B1B1B
|
||||
clickable: false
|
||||
- label:
|
||||
id: alert_subtitle
|
||||
x: ${ALERT_TEXT_X}
|
||||
y: ${ALERT_SUBTITLE_Y}
|
||||
width: ${ALERT_TEXT_W}
|
||||
height: ${ALERT_SUBTITLE_H}
|
||||
long_mode: WRAP
|
||||
text: ""
|
||||
text_font: sublabel_big
|
||||
text_color: 0x3A3A3C
|
||||
clickable: false
|
||||
- obj:
|
||||
id: alert_ok
|
||||
align: BOTTOM_RIGHT
|
||||
x: -${ALERT_BUTTON_INSET}
|
||||
y: -${ALERT_BUTTON_INSET}
|
||||
width: ${ALERT_BUTTON_W}
|
||||
height: ${ALERT_BUTTON_H}
|
||||
radius: 999
|
||||
bg_color: 0x1B1B1B
|
||||
bg_opa: COVER
|
||||
border_width: 0
|
||||
shadow_width: 0
|
||||
pad_all: 0
|
||||
clickable: true
|
||||
scrollable: false
|
||||
pressed:
|
||||
bg_color: 0x3A3A3C
|
||||
bg_opa: COVER
|
||||
on_click:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return cyd::touch_guard.accept(millis(), 13);'
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "ok"
|
||||
widgets:
|
||||
- label:
|
||||
id: alert_ok_label
|
||||
align: CENTER
|
||||
text: "Oké"
|
||||
text_font: headline
|
||||
text_color: 0xFFFFFF
|
||||
clickable: false
|
||||
|
||||
pages:
|
||||
- id: home_page
|
||||
styles: style_bg_grad
|
||||
@@ -4924,6 +5085,9 @@ script:
|
||||
- delay: 150ms
|
||||
- lambda: guition::check_geometry(id(vacuum_overlay));
|
||||
- lvgl.widget.hide: vacuum_overlay
|
||||
- lvgl.widget.show: alert_overlay
|
||||
- delay: 150ms
|
||||
- lvgl.widget.hide: alert_overlay
|
||||
- lambda: 'if (!id(ui_refresh).is_running()) id(ui_refresh).execute();'
|
||||
- logger.log: "UI_TEST COMPLETE"
|
||||
|
||||
@@ -5000,6 +5164,104 @@ script:
|
||||
- lvgl.widget.hide: climate_mode_overlay
|
||||
- lvgl.widget.hide: vacuum_overlay
|
||||
|
||||
# ---------- ALERT (HA action show_alert) ----------
|
||||
# The screen wakes, keeps its normal brightness and shows the card until Oké or the
|
||||
# timeout (0: until Oké); the standby interval waits on alert_active. A new alert
|
||||
# replaces the current one; every ending reports itself as esphome.screen_alert.
|
||||
- id: alert_show
|
||||
mode: restart
|
||||
parameters:
|
||||
title: string
|
||||
subtitle: string
|
||||
icon: string
|
||||
color: string
|
||||
button_text: string
|
||||
timeout: int
|
||||
flash: bool
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(alert_active)) id(alert_report).execute("replaced");
|
||||
const auto alert = screen_alert::make(title, subtitle, icon, color, button_text, timeout, flash, ${ALERT_TITLE_MAX}, ${ALERT_SUBTITLE_MAX}, ${ALERT_BUTTON_MAX});
|
||||
id(alert_active) = true;
|
||||
id(alert_title_text) = alert.title;
|
||||
id(alert_timeout_seconds) = alert.timeout_seconds;
|
||||
id(alert_flash_requested) = alert.flash;
|
||||
lv_label_set_text(id(alert_icon), alert.icon.c_str());
|
||||
lv_label_set_text(id(alert_title), alert.title.c_str());
|
||||
lv_label_set_text(id(alert_subtitle), alert.subtitle.c_str());
|
||||
lv_label_set_text(id(alert_ok_label), alert.button.c_str());
|
||||
lv_obj_set_style_bg_color(id(alert_card), lv_color_hex(alert.color), LV_PART_MAIN);
|
||||
ESP_LOGI("alert", "show \"%s\" timeout=%d flash=%d", alert.title.c_str(), alert.timeout_seconds, (int) alert.flash);
|
||||
- script.execute: wake_display
|
||||
- lvgl.widget.show: alert_overlay
|
||||
- script.stop: alert_timeout
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_flash_requested);'
|
||||
then:
|
||||
- script.execute: alert_flash
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_timeout_seconds) > 0;'
|
||||
then:
|
||||
- script.execute:
|
||||
id: alert_timeout
|
||||
seconds: !lambda 'return id(alert_timeout_seconds);'
|
||||
|
||||
- id: alert_dismiss
|
||||
parameters:
|
||||
reason: string
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(alert_active);'
|
||||
then:
|
||||
- lambda: |-
|
||||
id(alert_active) = false;
|
||||
id(last_touch_ms) = millis();
|
||||
ESP_LOGI("alert", "dismissed: %s", reason.c_str());
|
||||
- lvgl.widget.hide: alert_overlay
|
||||
- script.stop: alert_timeout
|
||||
- script.stop: alert_flash
|
||||
- lambda: 'id(set_backlight).execute(screen_settings::current.brightness, 80);'
|
||||
- script.execute:
|
||||
id: alert_report
|
||||
action: !lambda 'return reason;'
|
||||
|
||||
# Four backlight blinks when the alert arrives; the screen then stays on as usual.
|
||||
- id: alert_flash
|
||||
mode: restart
|
||||
then:
|
||||
- repeat:
|
||||
count: 4
|
||||
then:
|
||||
- lambda: 'id(set_backlight).execute(0, 60);'
|
||||
- delay: 140ms
|
||||
- lambda: 'id(set_backlight).execute(screen_settings::current.brightness, 60);'
|
||||
- delay: 180ms
|
||||
|
||||
- id: alert_timeout
|
||||
mode: restart
|
||||
parameters:
|
||||
seconds: int
|
||||
then:
|
||||
- delay: !lambda 'return static_cast<uint32_t>(seconds) * 1000UL;'
|
||||
- script.execute:
|
||||
id: alert_dismiss
|
||||
reason: "timeout"
|
||||
|
||||
# Home Assistant adds device_id; action is ok, timeout, replaced or remote.
|
||||
- id: alert_report
|
||||
parameters:
|
||||
action: string
|
||||
then:
|
||||
- homeassistant.event:
|
||||
event: esphome.screen_alert
|
||||
data:
|
||||
action: !lambda 'return action;'
|
||||
title: !lambda 'return id(alert_title_text);'
|
||||
screen: !lambda 'return App.get_name();'
|
||||
|
||||
- id: wake_display
|
||||
mode: restart
|
||||
then:
|
||||
|
||||
Reference in New Issue
Block a user