Files
homeassistant_espscreen/screen_manager/app/static/index.html
T
Max Gramser 3e959b3df9 Put ESP Screens in English and keep layouts when entity IDs change (0.2.40)
Everything a user sees or reads is now English: both boards' labels,
status replies and logs, the ESP Screens editor and Alerts cheatsheet,
and the README and guides (docs/TILES.md, CALIBRATING.md, ACCEPTANCE.md
and TROUBLESHOOTING.md replace the Dutch file names). Labels follow
Home Assistant's own English names (Heat/Cool modes, Heating/Cooling
actions, Away, Returning to dock, weather conditions), dates use English
abbreviations and the top bar writes numbers the English way. Docs use
HA 2026.9's menu names (Settings -> Apps, App store, Settings -> Tools).
Unused legacy files (home-like.yaml, buttons.yaml, a.out) are removed.

Firmware 0.2.34 names its entities in English. Home Assistant registers
a renamed ESPHome entity under a new entity ID, so the inbox
text.<screen>_tegelinstellingen becomes text.<screen>_tile_settings and
the layout stored under the old ID would be lost. The manager now
recognises the screen by its device, during a run or after a restart,
and moves its layout and update history along; the Update button and
the nightly round follow the screen through the rename. Screens that
still run 0.2.33 or older keep working: both languages are matched.

Main is the only release branch from now on.

Tested on a Home Assistant Yellow (HA 2026.9.1) with both bench boards:
see docs/TEST_RESULTS_0240.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 02:08:43 +02:00

480 lines
20 KiB
HTML
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.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>ESP Screens</title>
<link rel="stylesheet" href="static/style.css" />
<script src="static/app.js" defer></script>
</head>
<body>
<header>
<div class="brand">
<span class="mark">▦</span>
<div>
<strong>ESP Screens</strong
><small>Tiles for your CYD and Guition, without reflashing</small>
</div>
</div>
<nav class="toolbar" aria-label="Actions">
<button id="new-screen" class="tool tool-primary">
<span class="tool-icon" aria-hidden="true">+</span>
<span class="tool-text"
><b>New screen</b><small>Connect and install</small></span
>
</button>
<button id="open-firmware" class="tool">
<span class="tool-icon" aria-hidden="true">⇪</span>
<span class="tool-text"
><b>Firmware & USB</b
><small>Build and install via USB or Wi-Fi</small></span
>
</button>
<button id="open-alerts" class="tool">
<span class="tool-icon" aria-hidden="true">!</span>
<span class="tool-text"
><b>Alerts</b
><small>Full-screen notifications, from an automation</small></span
>
</button>
</nav>
</header>
<main>
<div class="intro">
<div>
<p class="eyebrow">HOME ASSISTANT</p>
<h1>Manage your remote screens here.</h1>
</div>
<span id="connection" role="status" class="badge">Connecting…</span>
</div>
<div class="workspace">
<aside>
<h2>My screens</h2>
<div id="screens"></div>
<div id="pending"></div>
<button class="quiet" id="refresh">↻ Refresh</button>
<div class="updates" id="updates" hidden>
<h2>Firmware updates</h2>
<p class="hint" id="updates-hint"></p>
<button id="update-all" hidden>Update all screens</button>
<label class="check">
<input type="checkbox" id="auto-update" />
<span
>Update automatically every night<small
>Between 03:00 and 06:00, one screen at a time. Stops on an
error and reports it in Home Assistant.</small
></span
>
</label>
</div>
</aside>
<section id="empty" class="empty">
<span class="empty-icon">▦</span>
<h2>Start with a screen</h2>
<p>
Connect a CYD or Guition via USB to your Home Assistant machine.
Profile, firmware, and the first flash happen in one window.
</p>
<button id="start">Install new screen</button>
</section>
<section id="editor" hidden>
<div class="editor-head">
<div>
<p class="eyebrow" id="screen-name"></p>
<h2>Make it your screen</h2>
</div>
<span id="delivery" class="badge"></span>
</div>
<section class="topbar-editor" id="topbar" aria-labelledby="topbar-title">
<div class="section-title">
<h3 id="topbar-title">Top bar</h3>
<span id="topbar-count"></span>
</div>
<div class="topbar-fields">
<label class="topbar-name"
>Left: name<input
id="title"
maxlength="60"
placeholder="For example: Living room"
/></label>
<div class="topbar-right">
<span class="topbar-caption" id="topbar-caption">Right: time, sensors, or a clock</span>
<div
id="topbar-chips"
class="topbar-chips"
role="list"
aria-labelledby="topbar-caption"
></div>
</div>
</div>
<p class="hint" id="topbar-hint"></p>
</section>
<div class="columns" id="tile-section">
<div class="tile-editor">
<div class="section-title">
<h3>Your tiles</h3>
<span id="count">0 / 10</span>
</div>
<div id="layout-preview" aria-label="Screen layout"></div>
<button id="add-page" class="quiet add-page" type="button">
+ Add page
</button>
<p id="no-tiles" class="hint">
Add your first light, scene, or device via the picker.
</p>
<p id="positions-hint" class="hint" hidden></p>
</div>
<div class="picker">
<label for="search">Add an entity</label
><input
id="search"
type="search"
placeholder="Search by name, device, or room…"
autocomplete="off"
/>
<div class="filters" id="filters"></div>
<div id="results" aria-live="polite"></div>
</div>
</div>
<details class="screen-settings" id="general-settings" open>
<summary>
Screen settings
<span class="hint">Brightness, quiet hours, and display</span>
</summary>
<p class="hint" id="settings-support"></p>
<div class="settings-grid" id="settings-fields"></div>
<p class="hint">
Night hours apply to the brightness during standby. The first
touch wakes the screen; the next one controls your home.
Matching start and end times turn the night window off.
</p>
</details>
<details class="screen-settings" id="inspector-section">
<summary>
Inspector
<span class="hint"
>Connection, status, and supported properties</span
>
</summary>
<button id="inspect" class="quiet">Read current data</button>
<div id="inspection-summary"></div>
<pre id="inspection">Select a screen and read the data.</pre>
</details>
<footer class="savebar">
<div>
<strong id="dirty">All saved</strong
><small id="save-detail"
>Changes apply without reflashing.</small
>
</div>
<button id="save">Save & send to screen</button>
</footer>
</section>
</div>
</main>
<dialog id="installer">
<form id="install-form">
<div class="dialog-head">
<div>
<p class="eyebrow">NEW SCREEN</p>
<h2 id="install-title">Connect and install.</h2>
</div>
<button
type="button"
class="quiet"
id="close-install"
aria-label="Close"
>
✕
</button>
</div>
<div id="install-setup">
<p>
Connect the screen with a USB data cable to the machine running Home
Assistant. ESP Screens creates its own profile with unique
keys, builds the firmware, and puts it straight on the screen.
</p>
<fieldset>
<legend>Which screen do you have?</legend>
<label class="board"
><input type="radio" name="board" value="cyd" checked /><span
><b>CYD · 2.8 inch</b
><small>ESP32-2432S028 · 320 × 240</small></span
></label
><label class="board"
><input type="radio" name="board" value="guition" /><span
><b>Guition · 4 inch</b
><small>ESP32-S3-4848S040 · 480 × 480 · GT911</small></span
></label
>
</fieldset>
<label
>Name<input
name="friendly_name"
required
maxlength="60"
placeholder="Living room screen"
autocomplete="off" /><small class="node-line"
>Device name <code id="node-preview">screen</code
><button type="button" class="link" id="edit-node">
customize
</button></small
><small
>Every screen gets its own profile with its own keys. Four
screens? Go through this four times with a different name.</small
></label
>
<label id="node-label" hidden
>Device name<input
name="name"
pattern="[a-z][a-z0-9-]{0,29}"
maxlength="30"
autocomplete="off" /><small
>Lowercase letters, digits, and dashes. A different name for
each screen.</small
></label
>
<fieldset id="wifi-fields" class="wifi" hidden disabled>
<legend>Wi-Fi</legend>
<p class="hint" id="wifi-status"></p>
<label id="wifi-ssid-label"
>Wi-Fi name (2.4 GHz)<input name="wifi_ssid" autocomplete="off"
/></label>
<label id="wifi-password-label"
>Wi-Fi password<input
name="wifi_password"
type="password"
autocomplete="new-password"
/></label>
</fieldset>
<label
>Install via<select name="target" id="install-target"></select
><small id="target-hint"></small
></label>
<p class="hint" id="install-note"></p>
<div class="install-actions">
<button type="submit" id="install-go">Install</button>
<span id="install-status" role="status"></span>
</div>
</div>
<div id="install-progress" hidden>
<div class="progress-head">
<span class="spin" id="progress-spin"></span>
<span class="outcome" id="progress-mark" hidden></span>
<strong id="progress-title"></strong>
</div>
<p id="progress-detail"></p>
<div id="install-result" hidden>
<div class="key-box">
<span>API key</span><code id="api-key"></code>
<button type="button" class="mini" id="copy-key">Copy</button>
</div>
<ol class="steps" id="install-steps"></ol>
</div>
<details id="install-log-wrap">
<summary>ESPHome log</summary>
<pre id="install-log"></pre>
</details>
<div class="install-actions">
<button type="button" id="install-retry" hidden>
Retry
</button>
<button type="button" class="quiet" id="install-close">
Close
</button>
</div>
</div>
</form>
</dialog>
<dialog id="firmware-dialog">
<div class="dialog-head">
<div>
<p class="eyebrow">FIRMWARE & USB</p>
<h2>Build and install screen firmware</h2>
</div>
<button id="close-firmware" class="quiet" aria-label="Close">✕</button>
</div>
<p>
The built-in ESPHome CLI uses your own profile (YAML with keys)
and secrets. Choose the screen's profile, then a USB port (screen
connected to the Home Assistant machine) or <b>Wi-Fi / OTA</b> with the hostname.
<b>Check</b> only validates, <b>Build only</b> compiles,
<b>Build & install</b> puts the firmware on the screen. Your tiles
stay as they are in ESP Screens. The first build takes a few minutes.
</p>
<label>ESPHome profile<select id="firmware-file"></select></label>
<label
>Install to<select id="firmware-port">
<option value="ota">Wi-Fi / OTA</option>
</select></label
>
<label id="firmware-host-label"
>IP address or hostname<input
id="firmware-host"
placeholder="screen-livingroom.local"
/></label>
<div class="yaml-actions">
<button id="firmware-validate" class="quiet">Check</button
><button id="firmware-build" class="quiet">Build only</button
><button id="firmware-install">Build & install</button>
</div>
<p id="firmware-status" role="status"></p>
<pre id="firmware-log"></pre>
</dialog>
<dialog id="tile-sheet" class="tile-sheet" aria-label="Configure tile"></dialog>
<dialog id="topbar-sheet" class="tile-sheet" aria-label="Top bar"></dialog>
<dialog id="alerts-dialog" class="alerts" aria-label="Alerts">
<div class="dialog-head">
<div>
<p class="eyebrow">ALERTS · CHEATSHEET</p>
<h2>A full-screen notification, from an automation.</h2>
</div>
<button id="close-alerts" class="quiet" aria-label="Close">✕</button>
</div>
<p>
Every screen has the <code>show_alert</code> action. It places a card over everything,
wakes the screen, and keeps the backlight at normal brightness until someone taps
the button or the timeout runs out. Home Assistant itself shows no explanation or
dropdowns for ESPHome actions; everything you can fill in is listed here.
</p>
<div class="alert-hero">
<div class="alert-mock" id="alert-mock" aria-hidden="true">
<div class="alert-mock-card">
<span class="mdi alert-mock-icon" id="alert-mock-icon"></span>
<strong id="alert-mock-title">Someone is at the door</strong>
<span id="alert-mock-subtitle">Door 3, back</span>
<button type="button" id="alert-mock-button" tabindex="-1">Coming</button>
</div>
</div>
<nav class="alerts-nav" aria-label="Sections">
<button type="button" data-jump="alerts-screens">Your screens</button>
<button type="button" data-jump="alerts-howto">In an automation</button>
<button type="button" data-jump="alerts-fields">The fields</button>
<button type="button" data-jump="alerts-icons">Icons</button>
<button type="button" data-jump="alerts-colors">Colors</button>
<button type="button" data-jump="alerts-behaviour">Behavior</button>
<button type="button" data-jump="alerts-events">Events</button>
<button type="button" data-jump="alerts-tips">Tips</button>
</nav>
</div>
<section id="alerts-screens">
<h3>Your screens</h3>
<p>
Every screen has its own action, with the device name in it. From firmware
<code id="alerts-min-firmware">0.2.31</code>; update an older screen under
Firmware updates.
</p>
<div id="alerts-screen-list"></div>
</section>
<section id="alerts-howto">
<h3>In an automation</h3>
<ol class="steps">
<li><b>Add action</b> and search for <b>ESPHome</b>. Choose your screen's action:
Home Assistant calls it "Performs the action show_alert of the node
<i>device name</i>".</li>
<li><b>Fill in the fields.</b> Home Assistant asks for all seven; leave what you don't
use empty (<code>""</code>, <code>0</code>, off).</li>
<li>Prefer YAML? Choose <b>Edit in YAML</b> on the action and paste the example
below.</li>
</ol>
<div class="alert-example">
<label
>Example for<select id="alerts-example-screen"></select
></label>
<div class="copy-line">
<pre id="alerts-example"></pre>
<button type="button" class="mini" id="alerts-example-copy">Copy YAML</button>
</div>
</div>
</section>
<section id="alerts-fields">
<h3>The fields</h3>
<p>
Text is free-form; the limit is in bytes, and an accented letter counts as two.
What doesn't fit gets an ellipsis (title) or is dropped (subtitle).
</p>
<div class="table-scroll"><table id="alerts-field-table"></table></div>
</section>
<section id="alerts-icons">
<h3>Icons</h3>
<p>
Fill in the name in <code>icon</code>, for example <code>doorbell</code>.
<code>mdi:doorbell</code> and the hex codepoint (<code>F12E6</code>) also work.
Only these icons are included in the firmware; any other name shows the
warning triangle. Tap an icon to copy its name.
</p>
<p class="alerts-subhead">Handy for notifications</p>
<div class="chips" id="alerts-suggested"></div>
<label class="alerts-search"
>Search for an icon<input
id="alerts-icon-search"
type="search"
placeholder="Search by name or description…"
autocomplete="off"
/></label>
<div id="alerts-icon-groups"></div>
</section>
<section id="alerts-colors">
<h3>Colors</h3>
<p>
Fill in the name in <code>color</code>. These are the pastel shades of the tiles,
with dark text. Empty or unknown gives the white card. Tap to copy.
</p>
<div class="swatches" id="alerts-swatches"></div>
</section>
<section id="alerts-behaviour">
<h3>Behavior</h3>
<ul class="alerts-list">
<li><b>Wakes the screen.</b> An alert immediately wakes a dimmed or dark screen and
appears above every page, every open light card, and the standby layer.</li>
<li><b>On until the button.</b> As long as the card is showing, the backlight stays at
normal brightness. Standby and night hours wait. After the button, the regular
standby time starts again.</li>
<li><b>Timeout.</b> <code>timeout: 0</code> waits for the button, however long that
takes. With <code>timeout: 60</code> the card disappears after a minute, but the
button closes it sooner.</li>
<li><b>Blinking.</b> <code>flash: true</code> blinks the backlight four times
when the alert arrives (about a second) and leaves the screen on afterward.</li>
<li><b>Replacing.</b> A new alert replaces the current one; there's no stack.
The replaced alert reports itself as <code>replaced</code>.</li>
<li><b>Closing remotely.</b> <code>dismiss_alert</code> clears the card,
for example if the door is already open. Without an alert, that action does nothing.</li>
<li><b>Tapping beside the card</b> does nothing; only the button closes it. That way a
wake-up tap never accidentally dismisses the alert.</li>
</ul>
</section>
<section id="alerts-events">
<h3>Events</h3>
<p>
Every end fires the event <code id="alerts-event-name">esphome.screen_alert</code>
with <code>action</code>, <code>title</code>, <code>screen</code> (the device name)
and the <code>device_id</code> that Home Assistant adds. Visible under
Settings → Tools → Events.
</p>
<div class="table-scroll"><table id="alerts-ending-table"></table></div>
<p class="alerts-subhead">Waiting until someone presses the button</p>
<div class="copy-line">
<pre id="alerts-wait-example"></pre>
<button type="button" class="mini" id="alerts-wait-copy">Copy YAML</button>
</div>
</section>
<section id="alerts-tips">
<h3>Tips</h3>
<ul class="alerts-list">
<li>Use a <b>color per kind of notification</b>: orange for the door, red for
smoke or water, green for "done". The text always stays dark and readable.</li>
<li>Keep the title <b>short</b>; the CYD shows about forty characters on one line.
Put details in the subtitle.</li>
<li>A <b>custom button text</b> turns the notification into a question: "Coming", "Seen",
"Turn off". The event then tells you who responded.</li>
<li>For an alert that resolves itself (the door opens, the laundry gets taken out)
close it in the same automation with <code>dismiss_alert</code>.</li>
<li>Multiple screens? Call each screen's action; they work independently and
each reports with its own <code>screen</code>.</li>
</ul>
</section>
</dialog>
<div id="toast" role="status" hidden></div>
</body>
</html>