Let Home Assistant automations switch Auto standby per screen, and teach the skill (0.2.48)

App 0.2.48 / firmware 0.2.41:
- Both boards expose the switch "Auto standby", the same standby_enabled setting as the checkbox
  in ESP Screens. Off wakes a dimmed screen and keeps it on; on counts the standby time from that
  moment. The change is saved on the screen and reported through esphome.screen_setting, so ESP
  Screens stores it too. No action runs at boot (restore_mode DISABLED).
- The Claude skill gains "Standby and brightness": the switch, Standby after and the three
  brightness numbers, with an example automation that keeps screens awake while someone is home
  and a light is on or a window is open.
- EASY_SETUP and the README describe the entities and the automation.

Tested through Home Assistant's API on both bench boards (CYD: dimmed -> off wakes in 1.1 s, stays
bright past the standby time, on dims again after 61 s); see docs/TEST_RESULTS_0248.md, which also
records a CYD rollback after the first OTA that points to memory headroom, not to this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-15 18:06:04 +02:00
parent 57c82fdd12
commit dffd6a90c6
13 changed files with 295 additions and 15 deletions
+2 -1
View File
@@ -92,7 +92,8 @@ The firmware and built-in CLI are tested with **ESPHome 2026.6.2**.
changed ("5 min ago", "Yesterday"). See [Top bar](#top-bar).
- **Screen settings:** standby time, normal and dimmed brightness,
night hours, 24- or 12-hour clock, return to the home page, and optional swiping
between pages.
between pages. Home Assistant automations can turn **Auto standby** off and on per
screen (firmware 0.2.41+), for example to keep a screen on while someone is home.
- **Guition rotation:** 0°, 90°, 180°, or 270°, directly from the management page.
Native LVGL rotation turns the display and touch together. The CYD keeps its fixed
orientation and its own calibration.
+35
View File
@@ -238,6 +238,41 @@ After this, changes to these settings don't need a new firmware flash.
| Swipe between pages | Native horizontal swipe, firmware 0.2.7+ | Off |
| Guition rotation | 0°, 90°, 180°, 270°, firmware 0.2.9+ | 0° |
Home Assistant shows the same settings on each screen's ESPHome device: the switch
**Auto standby** (firmware 0.2.41+) and the numbers **Standby after**, **Normal brightness**,
**Standby brightness** and **Night brightness**. Changing them there, for example from an
automation, also changes them in ESP Screens and keeps them after a restart. Turning Auto
standby off wakes the screen and keeps it on; turning it on counts the standby time from
that moment. To keep a screen on while someone is home and a light is on:
```yaml
alias: Keep the kitchen screen awake
mode: restart
triggers:
- trigger: state
entity_id: [person.alex, light.living_room]
actions:
- if:
- condition: state
entity_id: person.alex
state: home
- condition: state
entity_id: light.living_room
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.kitchen_screen_auto_standby
else:
- action: switch.turn_on
target:
entity_id: switch.kitchen_screen_auto_standby
```
Every change is saved on the screen, so switch on changes that happen a few times a day,
not on every motion. ESP Screens → Settings → Claude installs a skill that writes such
automations for you.
Night hours use the ESPHome device's timezone and the time from HA.
Without a valid time, the screen uses the regular standby brightness; matching
start and end times turn the night window off. At 0%, only the
+14
View File
@@ -176,6 +176,20 @@ icons sit off-center in the browser); run `generate_packages.py` afterward.
The `MDI_GLYPH_*` substitutions are retired: `TILEn_ICON` in manual
profiles must come from the set. No changed preferences or keys.
### Compatibility 0.2.48 / firmware 0.2.41
Storage, protocol, preferences and keys are unchanged.
- Both profiles add a template switch `setting_auto_standby` ("Auto standby", entity category config,
`restore_mode: DISABLED`, state from `screen_settings::current.standby_enabled` through its lambda).
Its actions change `standby_enabled`, save the settings preference, send the existing
`esphome.screen_setting` event (`standby_enabled`, 1/0; the app already stores bool settings from it)
and run `apply_screen_settings`, which wakes a dimmed screen when standby is off. Turning it on sets
`last_touch_ms`, so the standby time counts from then.
- `claude_skill.text()` gains "Standby and brightness" (the switch, the four numbers, an example
automation); `core.AUTO_STANDBY_MIN_FIRMWARE` is 0.2.41. The skill description stays under 200 bytes.
An installed skill shows as outdated until it is installed again.
### Compatibility 0.2.47 / firmware 0.2.40
Firmware and board profiles; the app only raises `FIRMWARE_VERSION`. Storage, protocol, preferences and
+43
View File
@@ -0,0 +1,43 @@
# Test results app 0.2.48 / firmware 0.2.41 (2026-09-15)
The Auto standby switch for Home Assistant automations and the standby section of the Claude skill.
See CHANGELOG 0.2.48 and RELEASING "Compatibility 0.2.48".
## Automated
- Python (`.venv-portal`): 170 tests OK; `tests/test_claude_skill.py` checks the new section (the
switch, the four numbers, the minimum firmware, the intro link) and parses the new example
automation (five YAML blocks), including that it triggers on every entity its condition reads.
- C++ (`clang++ -std=c++17 -Wall -Wextra -Werror -I . -I components/smart_display`): 13/13 PASS.
- `generate_packages.py --check` green, `generate_icons.py --check` verified.
- ESPHome 2026.6.2 compile SUCCESS, one after another: `easy-cyd-device.yaml` (RAM 32.0%, flash
78.6%), `easy-guition-device.yaml` (RAM 33.0%, flash 19.0%), `guition-device.yaml` (RAM 33.1%, flash 20.0%)
and `device.yaml` (RAM 32.1%, flash 83.3%). Packages carry `SCREEN_FIRMWARE_VERSION` 0.2.41.
## Bench boards (OTA) and Home Assistant
Both boards run 0.2.41. The switch was driven only through Home Assistant's REST API, the way an
automation does it, and watched through the backlight light entity and the app's inventory.
- CYD (standby after 60 s): the screen had dimmed to 55 %. `switch.turn_off` switched the entity off and
brought the backlight to 100 % within 1.1 s; the app's stored settings showed `standby_enabled: false`.
After 80 s without a touch the screen was still at 100 %. `switch.turn_on` switched it on and the screen
dimmed again after 61 s. The stored setting returned to `true`.
- Guition: `switch.turn_off` switched the entity off within 1.2 s and the screen stayed bright for 30 s;
`switch.turn_on` switched it back on; the stored setting returned to `true`.
## Observed on the CYD, not caused by this release
- The first OTA of 0.2.41 crashed within its first minute and the bootloader rolled back to 0.2.40 by
itself ("OTA rollback detected"). A second OTA of the same build booted, was marked successful and
passed the test above without a restart.
- Around the crash the CYD logged LVGL failing to allocate 13.8 KB layer buffers and a task watchdog
reset with a backtrace in the API connection code. The CYD also restarted twice on 0.2.40 while a
diagnostic script opened API connections every few seconds. Heap after the boot sync is about 70 KB.
This points to the CYD's memory headroom under bursts (boot sync, several API clients, object
opacity layers), not to the switch; a separate check of the CYD's LVGL layer use is due.
## Not tested / for the owner
- An automation of the owner's own that switches Auto standby over a day.
- Installing the updated skill from Settings → Claude and letting Claude write the automation.
+28 -1
View File
@@ -1,7 +1,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.40"
SCREEN_FIRMWARE_VERSION: "0.2.41"
# 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"
@@ -1933,6 +1933,33 @@ text_sensor:
switch:
- platform: restart
name: "Restart"
# Auto standby, the same setting as the checkbox in ESP Screens (firmware 0.2.41+), so Home Assistant
# automations can keep a screen on. Off wakes the screen and keeps it on; on counts the standby time
# from that moment. Nothing runs at boot: the switch follows the saved setting.
- platform: template
id: setting_auto_standby
name: "Auto standby"
icon: "mdi:sleep"
entity_category: config
restore_mode: DISABLED
lambda: return screen_settings::current.standby_enabled;
turn_on_action:
- lambda: |-
auto &s = screen_settings::current;
id(last_touch_ms) = millis();
if (s.standby_enabled) return;
s.standby_enabled = true;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 1);
id(apply_screen_settings).execute();
turn_off_action:
- lambda: |-
auto &s = screen_settings::current;
if (!s.standby_enabled) return;
s.standby_enabled = false;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 0);
id(apply_screen_settings).execute();
# Two SPI buses used by the CYD:
# - lcd: built-in display
+28 -1
View File
@@ -57,7 +57,7 @@
############################################################
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.40"
SCREEN_FIRMWARE_VERSION: "0.2.41"
# 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.
@@ -2116,6 +2116,33 @@ text_sensor:
switch:
- platform: restart
name: "Restart"
# Auto standby, the same setting as the checkbox in ESP Screens (firmware 0.2.41+), so Home Assistant
# automations can keep a screen on. Off wakes the screen and keeps it on; on counts the standby time
# from that moment. Nothing runs at boot: the switch follows the saved setting.
- platform: template
id: setting_auto_standby
name: "Auto standby"
icon: "mdi:sleep"
entity_category: config
restore_mode: DISABLED
lambda: return screen_settings::current.standby_enabled;
turn_on_action:
- lambda: |-
auto &s = screen_settings::current;
id(last_touch_ms) = millis();
if (s.standby_enabled) return;
s.standby_enabled = true;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 1);
id(apply_screen_settings).execute();
turn_off_action:
- lambda: |-
auto &s = screen_settings::current;
if (!s.standby_enabled) return;
s.standby_enabled = false;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 0);
id(apply_screen_settings).execute();
# Two SPI buses used by the CYD:
# - lcd: built-in display
+28 -1
View File
@@ -58,7 +58,7 @@
############################################################
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.40"
SCREEN_FIRMWARE_VERSION: "0.2.41"
# 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.
@@ -2047,6 +2047,33 @@ text_sensor:
switch:
- platform: restart
name: "Restart"
# Auto standby, the same setting as the checkbox in ESP Screens (firmware 0.2.41+), so Home Assistant
# automations can keep a screen on. Off wakes the screen and keeps it on; on counts the standby time
# from that moment. Nothing runs at boot: the switch follows the saved setting.
- platform: template
id: setting_auto_standby
name: "Auto standby"
icon: "mdi:sleep"
entity_category: config
restore_mode: DISABLED
lambda: return screen_settings::current.standby_enabled;
turn_on_action:
- lambda: |-
auto &s = screen_settings::current;
id(last_touch_ms) = millis();
if (s.standby_enabled) return;
s.standby_enabled = true;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 1);
id(apply_screen_settings).execute();
turn_off_action:
- lambda: |-
auto &s = screen_settings::current;
if (!s.standby_enabled) return;
s.standby_enabled = false;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 0);
id(apply_screen_settings).execute();
# Two SPI buses used by the CYD:
# - lcd: built-in display
+28 -1
View File
@@ -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.40"
SCREEN_FIRMWARE_VERSION: "0.2.41"
# 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"
@@ -1864,6 +1864,33 @@ text_sensor:
switch:
- platform: restart
name: "Restart"
# Auto standby, the same setting as the checkbox in ESP Screens (firmware 0.2.41+), so Home Assistant
# automations can keep a screen on. Off wakes the screen and keeps it on; on counts the standby time
# from that moment. Nothing runs at boot: the switch follows the saved setting.
- platform: template
id: setting_auto_standby
name: "Auto standby"
icon: "mdi:sleep"
entity_category: config
restore_mode: DISABLED
lambda: return screen_settings::current.standby_enabled;
turn_on_action:
- lambda: |-
auto &s = screen_settings::current;
id(last_touch_ms) = millis();
if (s.standby_enabled) return;
s.standby_enabled = true;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 1);
id(apply_screen_settings).execute();
turn_off_action:
- lambda: |-
auto &s = screen_settings::current;
if (!s.standby_enabled) return;
s.standby_enabled = false;
if (runtime_tiles::enabled) runtime_tiles::settings_preference.save(&s);
runtime_tiles::setting_event("standby_enabled", 0);
id(apply_screen_settings).execute();
# Two SPI buses used by the CYD:
# - lcd: built-in display
+8
View File
@@ -1,3 +1,11 @@
## 0.2.48 (firmware 0.2.41)
Keep a screen awake from a Home Assistant automation.
- **Auto standby in Home Assistant.** Every screen gets the switch **Auto standby**, the same setting as the checkbox in ESP Screens. Turn it off and a dimmed screen wakes at once and stays on; turn it on and the screen dims again after its standby time, counted from that moment. So an automation can keep the screens on while someone is home and the lights are on or a window is open. A change shows in ESP Screens too and is kept after a restart.
- **The Claude skill knows it.** The skill under Settings → Claude now also covers standby and brightness: the Auto standby switch, Standby after and the three brightness numbers, with an example automation. Install it again from the Settings page to get the new version.
- Firmware 0.2.41 for both boards; the app offers the update.
## 0.2.47 (firmware 0.2.40)
The new climate card comes to the Guition, with fan and swing right on the card.
+59 -5
View File
@@ -13,12 +13,13 @@ import zipfile
import tile_icons
from core import (ALERT_ENDINGS, ALERT_EVENT, ALERT_FALLBACK_ICON, ALERT_FIELDS, ALERT_LIMITS, ALERT_MAX_TIMEOUT,
ALERT_MIN_FIRMWARE, ALERT_SUGGESTED_ICONS, BROADCAST_DISMISS, BROADCAST_SHOW, TILE_BACKGROUNDS)
ALERT_MIN_FIRMWARE, ALERT_SUGGESTED_ICONS, AUTO_STANDBY_MIN_FIRMWARE, BROADCAST_DISMISS, BROADCAST_SHOW,
TILE_BACKGROUNDS)
NAME = 'esp-screens'
# claude.ai accepts at most 200 characters; Claude Code picks the skill by this sentence.
DESCRIPTION = ('Show alerts or notifications on ESP Screens (CYD and Guition touchscreens run from Home Assistant): '
'all screens or one, now or in an automation, with the icons and colors they support.')
DESCRIPTION = ('Alerts and standby on ESP Screens (CYD and Guition touchscreens run from Home Assistant): alerts on '
'all screens or one with the icons they support, and an automation that keeps screens awake.')
TYPES = {'string': 'text', 'int': 'number', 'bool': 'on/off'}
def skill_dir(config=None):
@@ -31,7 +32,8 @@ def _limit(name, kind):
return f'0 to {ALERT_MAX_TIMEOUT} s' if kind == 'int' else ''
def text():
"""SKILL.md: when to use it, the event for every screen, the per-screen action, fields, colors and icons."""
"""SKILL.md: when to use it, the event for every screen, the per-screen action, fields, colors and icons,
then the standby and brightness entities every screen has in Home Assistant."""
fields = '\n'.join(f'| `{name}` | {TYPES[kind]} | {help_} | {_limit(name, kind)} |' for name, kind, _, help_, _ in ALERT_FIELDS)
colors = ', '.join(f"`{name}` ({item['label']})" for name, item in TILE_BACKGROUNDS.items() if item['color'])
suggested = ', '.join(f'`{name}`' for name in ALERT_SUGGESTED_ICONS)
@@ -43,10 +45,12 @@ name: {NAME}
description: {DESCRIPTION}
---
# Alerts on ESP Screens
# Alerts and standby on ESP Screens
Made by ESP Screen Manager (ESP Screens → Settings → Claude). Installing it again from there replaces this file, so changes made here get lost.
Two things Home Assistant can do with the screens: show an alert (below), and keep a screen awake or let it dim ([Standby and brightness](#standby-and-brightness)).
An alert is a card over the whole screen with an icon, a title, a subtitle and one button. It wakes the screen and stays until someone presses the button or the timeout runs out. A new alert replaces the one showing.
## All screens: fire an event
@@ -160,6 +164,56 @@ actions:
sequence:
- event: {BROADCAST_DISMISS}
```
## Standby and brightness
Every screen has these entities in Home Assistant, on its ESPHome device. `<screen>` stands for the start Home Assistant gave the screen's entity IDs, the same as in `text.<screen>_tile_settings`; look them up rather than guessing.
| Entity | What it does |
|---|---|
| `switch.<screen>_auto_standby` | On: the screen dims after the standby time without a touch. Off: the screen wakes up and stays on. Firmware {AUTO_STANDBY_MIN_FIRMWARE} or newer. |
| `number.<screen>_standby_after` | Seconds without a touch before standby, 60 to 86400. |
| `number.<screen>_normal_brightness` | Brightness while in use, 5 to 100 %. |
| `number.<screen>_standby_brightness` | Brightness in standby, 0 to 100 %, at most the normal brightness. |
| `number.<screen>_night_brightness` | Brightness in standby during the night hours set in ESP Screens, 0 to 100 %. |
These are the same settings as in ESP Screens: a change made from Home Assistant shows there too and stays after a restart. Turning Auto standby on again counts the standby time from that moment. Every change is saved on the screen, so switch on changes that happen a few times a day (someone comes home, a light goes on, a window opens), never on every motion.
To keep screens on while something is going on at home, turn Auto standby off when the situation starts and on when it ends, all from one automation. Example with placeholders for the user's own entities:
```yaml
alias: Keep the screens awake
mode: restart
triggers:
- trigger: state
entity_id:
- person.alex
- light.living_room
- binary_sensor.bedroom_window
actions:
- if:
- condition: state
entity_id: person.alex
state: home
- condition: or
conditions:
- condition: state
entity_id: light.living_room
state: "on"
- condition: state
entity_id: binary_sensor.bedroom_window
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.kitchen_screen_auto_standby
else:
- action: switch.turn_on
target:
entity_id: switch.kitchen_screen_auto_standby
```
Replace the person, light, window and screen with the real entity IDs (ask which screens when there are several), and leave out conditions the user did not ask for.
'''
def status(directory):
+3 -1
View File
@@ -17,7 +17,9 @@ WEEKDAYS = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
REPO = 'https://github.com/MaxGramser/homeassistant_espscreen'
REFS = {'cyd': 'main', 'guition': 'main'}
# Firmware shipped with this app release; screens below it get an update offer.
FIRMWARE_VERSION = '0.2.40'
FIRMWARE_VERSION = '0.2.41'
# The Auto standby switch a screen offers Home Assistant automations.
AUTO_STANDBY_MIN_FIRMWARE = '0.2.41'
ATTRS = frozenset('brightness percentage current_position current_temperature temperature current_humidity min_temp max_temp target_temp_step supported_color_modes hvac_modes hvac_action hs_color color_temp_kelvin min_color_temp_kelvin max_color_temp_kelvin fan_speed_list unit_of_measurement battery_level fan_speed volume_level is_volume_muted media_title options min max step temperature_unit supported_features device_class next_rising next_setting finishes_at duration remaining humidity wind_speed wind_speed_unit apparent_temperature fan_modes swing_modes fan_mode swing_mode'.split())
# Attributes whose boolean value the screen needs; every other bool stays behind.
BOOL_ATTRS = frozenset(['is_volume_muted'])
+1 -1
View File
@@ -1,5 +1,5 @@
name: ESP Screen Manager
version: "0.2.47"
version: "0.2.48"
slug: esp_screen_manager
description: Choose tiles for your CYD and Guition touchscreen, without reflashing.
url: https://github.com/MaxGramser/homeassistant_espscreen
+18 -3
View File
@@ -11,7 +11,7 @@ ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'screen_manager/app'))
import claude_skill # noqa: E402
import tile_icons # noqa: E402
from core import ALERT_EVENT, ALERT_FIELDS, ALERT_LIMITS, ALERT_MIN_FIRMWARE, BROADCAST_DISMISS, BROADCAST_SHOW, TILE_BACKGROUNDS # noqa: E402
from core import ALERT_EVENT, ALERT_FIELDS, ALERT_LIMITS, ALERT_MIN_FIRMWARE, AUTO_STANDBY_MIN_FIRMWARE, BROADCAST_DISMISS, BROADCAST_SHOW, TILE_BACKGROUNDS # noqa: E402
HAS_YAML = importlib.util.find_spec('yaml') is not None
HAS_AIOHTTP = importlib.util.find_spec('aiohttp') is not None
@@ -27,7 +27,7 @@ class SkillText(unittest.TestCase):
self.assertIsNotNone(front)
self.assertEqual(front[1], 'esp-screens')
self.assertLessEqual(len(front[2]), 200, 'claude.ai refuses longer descriptions')
for words in ('ESP Screens', 'alerts', 'all screens', 'automation', 'icons'):
for words in ('ESP Screens', 'alerts', 'all screens', 'automation', 'icons', 'awake'):
self.assertIn(words, front[2])
self.assertEqual(text, claude_skill.text(), 'same text every time, so status() can compare')
self.assertNotRegex(text, r'\{[A-Z_]+\}', 'no placeholder left over')
@@ -44,6 +44,13 @@ class SkillText(unittest.TestCase):
for name, item in TILE_BACKGROUNDS.items():
if item['color']:
self.assertIn(f'`{name}`', text)
# Standby from automations (0.2.48): the switch, the numbers and when the switch arrived.
standby = text.split('## Standby and brightness', 1)[1]
for entity in ('switch.<screen>_auto_standby', 'number.<screen>_standby_after', 'number.<screen>_normal_brightness',
'number.<screen>_standby_brightness', 'number.<screen>_night_brightness'):
self.assertIn(f'`{entity}`', standby)
self.assertIn(AUTO_STANDBY_MIN_FIRMWARE, standby)
self.assertIn('(#standby-and-brightness)', text, 'the intro links to the section')
icons = text.split('## Icons', 1)[1].split('## When an alert ends', 1)[0]
self.assertEqual(set(re.findall(r'`([a-z0-9-]+)`', icons)) - {'icon'}, set(tile_icons.GLYPHS), 'exactly the glyphs the firmware carries')
@@ -51,7 +58,7 @@ class SkillText(unittest.TestCase):
def test_every_yaml_example_parses(self):
import yaml
blocks = re.findall(r'```yaml\n(.*?)```', claude_skill.text(), re.S)
self.assertEqual(len(blocks), 4)
self.assertEqual(len(blocks), 5)
parsed = [yaml.safe_load(block) for block in blocks]
self.assertEqual(parsed[0]['actions'][0]['event'], BROADCAST_SHOW)
self.assertEqual(set(parsed[0]['actions'][0]['event_data']), {name for name, *_ in ALERT_FIELDS})
@@ -59,6 +66,14 @@ class SkillText(unittest.TestCase):
self.assertEqual(parsed[2][0]['wait_for_trigger'][0]['event_type'], ALERT_EVENT)
choose = parsed[3]['actions'][0]['choose']
self.assertEqual([option['sequence'][0]['event'] for option in choose], [BROADCAST_SHOW, BROADCAST_DISMISS])
awake = parsed[4]
self.assertEqual(awake['mode'], 'restart')
branch = awake['actions'][0]
self.assertEqual((branch['then'][0]['action'], branch['else'][0]['action']), ('switch.turn_off', 'switch.turn_on'))
self.assertTrue(branch['then'][0]['target']['entity_id'].endswith('_auto_standby'))
watched = set(awake['triggers'][0]['entity_id'])
conditions = {branch['if'][0]['entity_id']} | {c['entity_id'] for c in branch['if'][1]['conditions']}
self.assertEqual(watched, conditions, 'the automation reacts to every entity its condition reads')
class Archive(unittest.TestCase):