Add readable pastel tile backgrounds and refresh setup documentation
This commit is contained in:
@@ -1,17 +1,132 @@
|
|||||||
# Home Assistant ESP Screens
|
# Home Assistant ESP Screens
|
||||||
|
|
||||||
**Nieuw scherm installeren? Begin met [Easy Setup](docs/EASY_SETUP.md).**
|
Een Home Assistant-bedieningsscherm dat je zelf indeelt. **ESP Screen Manager**
|
||||||
Installeer ESP Screen Manager in Home Assistant, download de YAML voor CYD of
|
beheert je tegels én bouwt en installeert de ESPHome-firmware vanuit Home Assistant.
|
||||||
Guition, bouw en flash vanuit dezelfde app via USB op je Raspberry en kies je tegels in de beheerpagina.
|
Geen blueprint, MQTT of long-lived token nodig voor normaal gebruik.
|
||||||
Zoeken op entiteit/apparaat/ruimte, slepen, opslaan — zonder opnieuw flashen.
|
|
||||||
|
|
||||||
Updates van de app behouden je indelingen. Nieuwe firmware installeer je via
|
**Nieuw scherm? Volg de [complete installatiehandleiding](docs/EASY_SETUP.md).**
|
||||||
ESPHome OTA met behoud van je eigen naam, wifi en sleutels.
|
Voor elke nieuwe gebruiker en elk nieuw apparaat maak je een eigen profiel.
|
||||||
Zie [de nieuwe kaarten, inspector en firmwarepagina](docs/WHATS_NEW_020.md) en
|
|
||||||
[updates publiceren](docs/RELEASING.md).
|
|
||||||
|
|
||||||
De handleiding hieronder blijft beschikbaar voor handmatige installatie via een
|
## Ondersteunde schermen
|
||||||
computer. Voor de handmatige Guition-route: [Guition](docs/GUITION.md).
|
|
||||||
|
| Scherm | Resolutie | Display / touch |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| CYD ESP32-2432S028 | 320 × 240 | ILI9341 / resistieve XPT2046 |
|
||||||
|
| Guition ESP32-S3-4848S040, 4 inch | 480 × 480 | ST7701S RGB / capacitieve GT911 |
|
||||||
|
|
||||||
|
Gebruik deze exacte bordvarianten: gelijkende productnamen kunnen andere
|
||||||
|
controllers of aansluitingen hebben. Wallbox-relais worden niet aangestuurd.
|
||||||
|
De firmware en ingebouwde CLI zijn getest met **ESPHome 2026.6.2**.
|
||||||
|
|
||||||
|
## Wat je kunt instellen
|
||||||
|
|
||||||
|
- **Tot twintig tegels**, verdeeld over maximaal vier vaste pagina's met zes
|
||||||
|
tegels. Zoek op entiteit, apparaat of ruimte en sleep om te ordenen.
|
||||||
|
- **Instellingen per tegel:** eigen naam, klikgedrag, een kleine slider waar
|
||||||
|
ondersteund, of een grote waarde voor bijvoorbeeld temperatuur en verbruik.
|
||||||
|
- **Pastel achtergronden per tegel:** kies rood voor een alles-uit-script,
|
||||||
|
groen voor alles-aan, of een andere kleur. Titel en status blijven donker en
|
||||||
|
leesbaar. De kleur verschijnt ook in het schermvoorbeeld; **Standaard** herstelt
|
||||||
|
de normale kleuren. Vereist firmware 0.2.10 of nieuwer.
|
||||||
|
- **Lampbediening:** helderheid, regenboogkleur en wittemperatuur volgens de
|
||||||
|
mogelijkheden van de lamp. Open de detailbediening met een lange aanraking.
|
||||||
|
- **Meer kaarten:** climate, vacuum, fan, cover, media player, sensoren,
|
||||||
|
select/input_select, number/input_number, schakelaars, scènes, scripts en
|
||||||
|
buttons. Een sensor kan een historiekaart voor 1, 6 of 24 uur openen.
|
||||||
|
- **Scherminstellingen:** standby-tijd, normale en gedimde helderheid,
|
||||||
|
nachturen, klok, terug naar de hoofdpagina en optioneel swipen tussen pagina's.
|
||||||
|
- **Guition-rotatie:** 0°, 90°, 180° of 270°, direct vanuit de beheerpagina.
|
||||||
|
De native LVGL-rotatie draait beeld en touch samen. De CYD behoudt zijn vaste
|
||||||
|
oriëntatie en eigen kalibratie.
|
||||||
|
- **Inspector:** controleer entiteiten, status en configuratie in ESP Screens.
|
||||||
|
Actiefeedback laat zien dat een opdracht onderweg is.
|
||||||
|
|
||||||
|
Functies hangen af van de mogelijkheden die Home Assistant voor een entiteit
|
||||||
|
meldt. De app moet blijven draaien om de schermen van actuele gegevens te voorzien.
|
||||||
|
|
||||||
|
## Installeren vanuit Home Assistant
|
||||||
|
|
||||||
|
Voor Home Assistant OS met Apps/Add-ons op **aarch64 of amd64**:
|
||||||
|
|
||||||
|
1. Open de appwinkel en voeg deze repository toe:
|
||||||
|
`https://github.com/MaxGramser/homeassistant_espscreen`.
|
||||||
|
2. Installeer **ESP Screen Manager**, start de app en open **ESP Screens**.
|
||||||
|
ESPHome Device Builder is optioneel: de ESPHome-CLI zit al in deze app.
|
||||||
|
3. Kies **Nieuw scherm**, selecteer CYD of Guition en geef een unieke naam.
|
||||||
|
Gebruik **Bewaar profiel in ESP Screens**. Bestaande `wifi_ssid` en
|
||||||
|
`wifi_password` in ESPHome `secrets.yaml` worden hergebruikt; bij een verse
|
||||||
|
installatie vraagt de wizard de wifi eenmalig. API- en OTA-sleutels worden
|
||||||
|
uniek aangemaakt en in je eigen apparaat-YAML bewaard.
|
||||||
|
4. Sluit het scherm met een USB-datakabel aan op de **Home Assistant-machine**.
|
||||||
|
Open **Firmware & USB**, kies het eigen profiel en de juiste USB-poort en
|
||||||
|
start **Bouwen & installeren**. Een eerste build kan meerdere minuten duren.
|
||||||
|
5. **CYD:** doorloop de kalibratie op het scherm. **Guition:** gebruikt GT911
|
||||||
|
zonder resistieve kalibratie. Koppel daarna het ontdekte ESPHome-apparaat in
|
||||||
|
**Instellingen → Apparaten & diensten**. Gebruik bij een sleutelvraag de
|
||||||
|
`api.encryption.key` uit je eigen YAML. Geef het apparaat toestemming om
|
||||||
|
Home Assistant-acties uit te voeren.
|
||||||
|
6. Selecteer het scherm in ESP Screens, kies je tegels en klik
|
||||||
|
**Opslaan & naar scherm**. Test vervolgens de fysieke bediening.
|
||||||
|
|
||||||
|
Je kunt later vanuit **Firmware & USB → Wifi / OTA** nieuwe firmware installeren.
|
||||||
|
Gebruik voor een bestaand scherm altijd het bestaande profiel; opnieuw een
|
||||||
|
installatieprofiel aanmaken genereert nieuwe sleutels.
|
||||||
|
|
||||||
|
## Tegels en kleuren aanpassen
|
||||||
|
|
||||||
|
Open **Tegels instellen**, klik een tegel in het schermvoorbeeld en open
|
||||||
|
**Bediening & weergave instellen**. Kies bij **Pastel achtergrond** een kleur,
|
||||||
|
zoals rood of groen. Pas eventueel de naam, klikactie, mini-slider of grote
|
||||||
|
waarde aan. Klik **Opslaan & naar scherm** om de wijzigingen toe te passen.
|
||||||
|
Dit vereist na de eerste ondersteunende firmware-update geen nieuwe flash.
|
||||||
|
|
||||||
|
Een kleur is een vaste keuze voor die tegel: hij blijft dus bijvoorbeeld rood
|
||||||
|
wanneer je het alles-uit-script gebruikt. De entiteitsstatus en actiefeedback
|
||||||
|
blijven afzonderlijk zichtbaar.
|
||||||
|
|
||||||
|
## Updates en behoud van je instellingen
|
||||||
|
|
||||||
|
| Wijziging | Actie |
|
||||||
|
| --- | --- |
|
||||||
|
| Tegels, namen, kleuren, volgorde of scherminstellingen | Opslaan in ESP Screens; geen firmwareflash |
|
||||||
|
| Nieuwe versie van de beheerpagina | ESP Screen Manager updaten in de HA-appwinkel |
|
||||||
|
| Nieuwe functie op het fysieke scherm | Bestaand profiel bijwerken via Firmware & USB → Wifi / OTA |
|
||||||
|
|
||||||
|
De eigen YAML en wifi/API/OTA-instellingen blijven in de ESPHome-configmap.
|
||||||
|
Tegelindelingen en opties staan in de permanente appdata. CYD-kalibratie en
|
||||||
|
schermvoorkeuren blijven op het apparaat opgeslagen. Updates vervangen deze
|
||||||
|
gebruikersgegevens niet. Maak wel normale Home Assistant-back-ups en bewaar je
|
||||||
|
apparaatprofielen; een app verwijderen of flashgeheugen wissen is geen update.
|
||||||
|
|
||||||
|
Zie [releasegeschiedenis](screen_manager/CHANGELOG.md) en
|
||||||
|
[releases en protocolcompatibiliteit](docs/RELEASING.md).
|
||||||
|
|
||||||
|
## Handleidingen en hulp bij installatie
|
||||||
|
|
||||||
|
- [Complete installatie vanuit ESP Screens](docs/EASY_SETUP.md)
|
||||||
|
- [Guition-hardware, montage en rotatie](docs/GUITION.md)
|
||||||
|
- [CYD-kalibratie en USB-diagnose](docs/CALIBREREN.md)
|
||||||
|
- [Fysieke acceptatietest](docs/ACCEPTATIE.md)
|
||||||
|
- [Instructies voor developers en LLM's](AGENTS.md)
|
||||||
|
|
||||||
|
Geef een developer of LLM een schone kopie van deze repository en bijvoorbeeld:
|
||||||
|
|
||||||
|
> Lees AGENTS.md, README.md en docs/EASY_SETUP.md. Help me dit CYD- of
|
||||||
|
> Guition-scherm via USB op mijn Home Assistant te installeren. Identificeer
|
||||||
|
> het bord en gebruik mijn bestaande profiel als dat er al is. Begeleid
|
||||||
|
> kalibratie, HA-koppeling, tegelkeuze en fysieke tests. Houd sleutels lokaal
|
||||||
|
> en geef aan welke controles werkelijk zijn uitgevoerd.
|
||||||
|
|
||||||
|
Een build bewijst niet dat fysieke touch of het paneelbeeld goed is. De eigenaar
|
||||||
|
moet het beeld controleren en de gevraagde tikken uitvoeren.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Oudere handmatige CYD-installatie via een computer</summary>
|
||||||
|
|
||||||
|
Onderstaande route gebruikt het oudere handmatige profiel met maximaal tien
|
||||||
|
tegels. De positiebeperkingen hiervan gelden niet voor de twintig runtime-tegels
|
||||||
|
van ESP Screen Manager. Gebruik voor nieuwe installaties bij voorkeur de route
|
||||||
|
hierboven; de handmatige instructies blijven beschikbaar voor onderhoud.
|
||||||
|
|
||||||
# CYD Home Assistant-bedieningsscherm
|
# CYD Home Assistant-bedieningsscherm
|
||||||
|
|
||||||
@@ -234,3 +349,5 @@ Project-, ESPHome-driver- en fontlicenties staan respectievelijk in `LICENSE`,
|
|||||||
`components/xpt2046/LICENSE` en `fonts/`. Historische borddiagnose staat in
|
`components/xpt2046/LICENSE` en `fonts/`. Historische borddiagnose staat in
|
||||||
[CYD_STABILITY.md](CYD_STABILITY.md); volg voor een **nieuwe** installatie de
|
[CYD_STABILITY.md](CYD_STABILITY.md); volg voor een **nieuwe** installatie de
|
||||||
handleidingen hierboven.
|
handleidingen hierboven.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ struct Tile {
|
|||||||
std::array<float,24> history{};
|
std::array<float,24> history{};
|
||||||
bool has_history = false;
|
bool has_history = false;
|
||||||
float battery = NAN, volume = NAN;
|
float battery = NAN, volume = NAN;
|
||||||
uint32_t supported = 0;
|
uint32_t supported = 0, background = 0;
|
||||||
std::string revision, pending_revision;
|
std::string revision, pending_revision;
|
||||||
uint32_t pending_since = 0;
|
uint32_t pending_since = 0;
|
||||||
bool pending = false, confirmed = false, local_feedback = false;
|
bool pending = false, confirmed = false, local_feedback = false;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "runtime_model.h"
|
#include "runtime_model.h"
|
||||||
|
#include "tile_palette.h"
|
||||||
#include "screen_settings.h"
|
#include "screen_settings.h"
|
||||||
#include "esphome/core/preferences.h"
|
#include "esphome/core/preferences.h"
|
||||||
#include "cyd_ui.h"
|
#include "cyd_ui.h"
|
||||||
@@ -136,6 +137,7 @@ inline std::string receive(const std::string &payload) {
|
|||||||
std::string revision = string(root["state"]); serializeJson(a, revision);
|
std::string revision = string(root["state"]); serializeJson(a, revision);
|
||||||
tile.observe(revision);
|
tile.observe(revision);
|
||||||
auto options = root["o"];
|
auto options = root["o"];
|
||||||
|
tile.background = tile_palette::color(string(options["background"],16));
|
||||||
tile.tap = string(options["tap"]); if (tile.tap.empty()) tile.tap="auto";
|
tile.tap = string(options["tap"]); if (tile.tap.empty()) tile.tap="auto";
|
||||||
tile.display = string(options["display"]); if (tile.display.empty()) tile.display="standard";
|
tile.display = string(options["display"]); if (tile.display.empty()) tile.display="standard";
|
||||||
tile.inline_control = string(options["inline"]); if (tile.inline_control.empty()) tile.inline_control="none";
|
tile.inline_control = string(options["inline"]); if (tile.inline_control.empty()) tile.inline_control="none";
|
||||||
@@ -531,19 +533,20 @@ inline void render(lv_obj_t *room) {
|
|||||||
auto color=lv_color_hex(accent);
|
auto color=lv_color_hex(accent);
|
||||||
if(t.domain()=="light" && on && t.has_hs_color)
|
if(t.domain()=="light" && on && t.has_hs_color)
|
||||||
color=lv_color_hsv_to_rgb(t.hue%360,t.saturation,100);
|
color=lv_color_hsv_to_rgb(t.hue%360,t.saturation,100);
|
||||||
auto circle_color=available?lv_color_mix(color,lv_color_hex(light_theme?0xFFFFFF:0x263B50),light_theme?38:65):lv_color_hex(light_theme?0xF0F0F0:0x263B50);
|
bool dark_text=light_theme || t.background!=0;
|
||||||
|
auto circle_color=available?lv_color_mix(color,lv_color_hex(dark_text?0xFFFFFF:0x263B50),dark_text?38:65):lv_color_hex(dark_text?0xF0F0F0:0x263B50);
|
||||||
// Darken the foreground slightly: very pale bulbs still need a visible icon.
|
// Darken the foreground slightly: very pale bulbs still need a visible icon.
|
||||||
auto icon_color=available?lv_color_mix(color,lv_color_hex(light_theme?0x333333:0xFFFFFF),light_theme?205:185):lv_color_hex(0x9E9E9E);
|
auto icon_color=available?lv_color_mix(color,lv_color_hex(dark_text?0x333333:0xFFFFFF),dark_text?205:185):lv_color_hex(0x9E9E9E);
|
||||||
lv_obj_set_style_bg_color(w.slider,color,LV_PART_INDICATOR);
|
lv_obj_set_style_bg_color(w.slider,color,LV_PART_INDICATOR);
|
||||||
lv_obj_set_style_bg_color(w.slider,lv_color_mix(color,lv_color_hex(light_theme?0xFFFFFF:0x263B50),30),LV_PART_MAIN);
|
lv_obj_set_style_bg_color(w.slider,lv_color_mix(color,lv_color_hex(dark_text?0xFFFFFF:0x263B50),30),LV_PART_MAIN);
|
||||||
lv_obj_set_style_bg_color(w.tile, lv_color_hex(light_theme ? 0xFFFFFF : (on ? 0xF5F1E8 : 0x526C85)), 0);
|
lv_obj_set_style_bg_color(w.tile, lv_color_hex(t.background ? t.background : (light_theme ? 0xFFFFFF : (on ? 0xF5F1E8 : 0x526C85))), 0);
|
||||||
lv_obj_set_style_border_width(w.tile, 1, 0);
|
lv_obj_set_style_border_width(w.tile, 1, 0);
|
||||||
lv_obj_set_style_border_opa(w.tile, LV_OPA_COVER, 0);
|
lv_obj_set_style_border_opa(w.tile, LV_OPA_COVER, 0);
|
||||||
lv_obj_set_style_border_color(w.tile, lv_color_hex(light_theme ? 0xDDDDDD : (on ? 0xF5F1E8 : 0x9CB3C8)), 0);
|
lv_obj_set_style_border_color(w.tile, t.background ? lv_color_mix(lv_color_hex(t.background),lv_color_hex(0x000000),220) : lv_color_hex(light_theme ? 0xDDDDDD : (on ? 0xF5F1E8 : 0x9CB3C8)), 0);
|
||||||
lv_obj_set_style_bg_color(w.circle,circle_color,0);
|
lv_obj_set_style_bg_color(w.circle,circle_color,0);
|
||||||
lv_obj_set_style_text_color(w.icon,icon_color,0);
|
lv_obj_set_style_text_color(w.icon,icon_color,0);
|
||||||
lv_obj_set_style_text_color(w.title, lv_color_hex(light_theme ? 0x1B1B1B : (on ? 0x172232 : 0xF3F5F7)), 0);
|
lv_obj_set_style_text_color(w.title, lv_color_hex(dark_text ? 0x1B1B1B : (on ? 0x172232 : 0xF3F5F7)), 0);
|
||||||
lv_obj_set_style_text_color(w.value, lv_color_hex(light_theme ? 0x616161 : (on ? 0x46525E : 0xF0F4F8)), 0);
|
lv_obj_set_style_text_color(w.value, lv_color_hex(t.background ? 0x46525E : (light_theme ? 0x616161 : (on ? 0x46525E : 0xF0F4F8))), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,6 +566,12 @@ inline bool check_tile_geometry() {
|
|||||||
fits=fits && value.y2<track.y1 && track.y2<=content.y2;
|
fits=fits && value.y2<track.y1 && track.y2<=content.y2;
|
||||||
}
|
}
|
||||||
if(!fits)ESP_LOGE("ui_test","Tile geometry FAIL slot=%u title_y=%d..%d value_y=%d..%d content_y=%d..%d",(unsigned)w.index,title.y1,title.y2,value.y1,value.y2,content.y1,content.y2);
|
if(!fits)ESP_LOGE("ui_test","Tile geometry FAIL slot=%u title_y=%d..%d value_y=%d..%d content_y=%d..%d",(unsigned)w.index,title.y1,title.y2,value.y1,value.y2,content.y1,content.y2);
|
||||||
|
if(w.index<model.count && model.tiles[w.index].background){
|
||||||
|
bool palette_ok=lv_color_eq(lv_obj_get_style_bg_color(w.tile,LV_PART_MAIN),lv_color_hex(model.tiles[w.index].background)) &&
|
||||||
|
lv_color_eq(lv_obj_get_style_text_color(w.title,LV_PART_MAIN),lv_color_hex(0x1B1B1B));
|
||||||
|
if(!palette_ok)ESP_LOGE("ui_test","Tile palette FAIL slot=%u",(unsigned)w.index);
|
||||||
|
fits=fits && palette_ok;
|
||||||
|
}
|
||||||
ok=ok && fits;
|
ok=ok && fits;
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace tile_palette {
|
||||||
|
// Match the editor palette; all backgrounds are chosen for dark text.
|
||||||
|
inline uint32_t color(const std::string &name) {
|
||||||
|
if(name=="red")return 0xFADADD;
|
||||||
|
if(name=="orange")return 0xFFE1C6;
|
||||||
|
if(name=="yellow")return 0xFFF0C2;
|
||||||
|
if(name=="green")return 0xD9EEDC;
|
||||||
|
if(name=="mint")return 0xD5F0EA;
|
||||||
|
if(name=="blue")return 0xD9EAFB;
|
||||||
|
if(name=="purple")return 0xE9DDF5;
|
||||||
|
if(name=="pink")return 0xF7DDEC;
|
||||||
|
if(name=="gray")return 0xE5E7EB;
|
||||||
|
return 0; // Automatic/default, including unknown future palette names.
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
-58
@@ -1,12 +1,6 @@
|
|||||||
# Installeren vanuit ESP Screens (vanaf 0.2.0)
|
# Installeren en beheren vanuit ESP Screens
|
||||||
|
|
||||||
De makkelijkste route is nu één app: **ESP Screen Manager**. Deze kan zelf
|
Een nieuw scherm, van USB naar dagelijks gebruik
|
||||||
ESPHome-profielen bewaren, bouwen en via USB of OTA installeren. Zie de
|
|
||||||
[complete stappen voor deze route](WHATS_NEW_020.md#firmware-zonder-een-tweede-beheerpagina).
|
|
||||||
De instructies hieronder blijven bruikbaar als je ESPHome Device Builder wilt
|
|
||||||
blijven gebruiken. Beide routes behouden dezelfde eigen YAML en secrets.
|
|
||||||
|
|
||||||
# Een nieuw scherm, van USB naar dagelijks gebruik
|
|
||||||
|
|
||||||
Met **ESP Screen Manager** kies je je tegels in Home Assistant. Je zoekt op
|
Met **ESP Screen Manager** kies je je tegels in Home Assistant. Je zoekt op
|
||||||
naam, apparaat, ruimte of entity-ID, zet ze in de gewenste volgorde en klikt
|
naam, apparaat, ruimte of entity-ID, zet ze in de gewenste volgorde en klikt
|
||||||
@@ -14,7 +8,8 @@ op **Opslaan & naar scherm**. Daarna blijft de status automatisch actueel.
|
|||||||
Je hoeft voor andere tegels **niet opnieuw te flashen**.
|
Je hoeft voor andere tegels **niet opnieuw te flashen**.
|
||||||
|
|
||||||
Dit werkt met Home Assistant OS op een 64-bits Raspberry Pi of een amd64-machine,
|
Dit werkt met Home Assistant OS op een 64-bits Raspberry Pi of een amd64-machine,
|
||||||
ESPHome Device Builder en een van deze exacte schermvarianten:
|
en een van deze exacte schermvarianten. De ESPHome-CLI zit in ESP Screen Manager;
|
||||||
|
ESPHome Device Builder is optioneel:
|
||||||
|
|
||||||
| Keuze | Hardware |
|
| Keuze | Hardware |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@@ -25,63 +20,55 @@ Andere schermen met ongeveer dezelfde naam kunnen andere pinnen hebben. Gebruik
|
|||||||
het bordprofiel dat bij de hardware hoort. Gebruik een USB-kabel die data ondersteunt.
|
het bordprofiel dat bij de hardware hoort. Gebruik een USB-kabel die data ondersteunt.
|
||||||
De wallbox-relais worden niet gebruikt.
|
De wallbox-relais worden niet gebruikt.
|
||||||
|
|
||||||
## 1. Installeer de twee apps
|
## 1. Installeer ESP Screen Manager
|
||||||
|
|
||||||
1. Open **Instellingen → Apps → Installeer een app** (in oudere HA-versies:
|
1. Open **Instellingen → Apps → Installeer een app** (in oudere HA-versies:
|
||||||
**Instellingen → Add-ons → Add-onwinkel**).
|
**Instellingen → Add-ons → Add-onwinkel**).
|
||||||
2. Installeer **ESPHome Device Builder**, start deze en zet hem in de zijbalk.
|
2. Open het menu rechtsboven → **Repositories** en voeg toe:
|
||||||
Gebruik ESPHome **2026.6.2 of nieuwer**. De release is met 2026.6.2 getest.
|
|
||||||
3. Open in de appwinkel het menu rechtsboven → **Repositories**. Voeg toe:
|
|
||||||
`https://github.com/MaxGramser/homeassistant_espscreen`.
|
`https://github.com/MaxGramser/homeassistant_espscreen`.
|
||||||
4. Zoek **ESP Screen Manager**, installeer en start deze. Zet **Starten bij
|
3. Installeer en start **ESP Screen Manager**. Zet **Starten bij opstarten**
|
||||||
opstarten** en **Tonen in zijbalk** aan. Open de webinterface.
|
en **Tonen in zijbalk** aan. Open de webinterface **ESP Screens**.
|
||||||
|
|
||||||
De beheerpagina draait binnen Home Assistant en gebruikt je HA-aanmelding.
|
Deze app bevat de geteste ESPHome 2026.6.2-CLI en draait binnen je HA-aanmelding.
|
||||||
Je hoeft geen extra gebruiker, MQTT, blueprint of long-lived token in te stellen.
|
Een tweede ESPHome-beheerpagina, MQTT, blueprint of long-lived token is niet nodig.
|
||||||
Installeer voor normaal gebruik de GitHub-versie: een handmatig gekopieerde lokale
|
Gebruik de GitHub-versie voor updates; een lokale test-add-on is een andere app.
|
||||||
test-add-on ontvangt geen updates uit GitHub.
|
|
||||||
|
|
||||||
## 2. Download je eigen installatie-YAML
|
## 2. Maak en bewaar je eigen apparaatprofiel
|
||||||
|
|
||||||
Klik in ESP Screens op **Nieuw scherm**. Kies CYD of Guition, een herkenbare naam
|
Klik **Nieuw scherm**. Kies CYD of Guition, een herkenbare naam en een unieke
|
||||||
en een unieke apparaatnaam zoals `scherm-keuken`. Klik **Maak installatie-YAML**. Gebruik **Kopieer YAML** om de tekst meteen in
|
apparaatnaam, bijvoorbeeld `scherm-keuken`. Klik **Bewaar profiel in ESP Screens**.
|
||||||
ESPHome te plakken, of **Download bestand**. Op een HTTP-verbinding kan Chrome
|
|
||||||
downloads blokkeren; de kopieeroptie blijft bruikbaar.
|
|
||||||
|
|
||||||
Bij **Bewaar profiel in ESP Screens** controleert de wizard automatisch de bestaande
|
De wizard controleert de bestaande ESPHome `secrets.yaml`. Met `wifi_ssid` en
|
||||||
ESPHome `secrets.yaml`. Zijn `wifi_ssid` en `wifi_password` aanwezig, dan hoef je
|
`wifi_password` aanwezig hoef je geen wifi in te vullen. Alleen als er nog geen
|
||||||
geen wifi in te vullen. Alleen bij een eerste installatie zonder secretsbestand
|
secretsbestand is, vraagt de wizard je 2,4GHz-wifi eenmalig. Een bestaand bestand
|
||||||
vraagt hij die gegevens één keer. Bestaande secrets worden niet overschreven.
|
met ontbrekende of ongeldige wifi-sleutels moet je eerst herstellen; het wordt
|
||||||
|
niet stilzwijgend overschreven.
|
||||||
|
|
||||||
Dit bestand bevat unieke API- en OTA-sleutels. Bewaar het. Maak voor ieder nieuw
|
Je apparaat-YAML bevat unieke API- en OTA-sleutels. Bewaar dit profiel en gebruik
|
||||||
scherm een nieuw bestand. Download voor een bestaand scherm niet telkens een nieuw
|
het opnieuw bij updates. Voor een bestaand scherm telkens een nieuw profiel
|
||||||
bestand: daarmee zou je nieuwe sleutels genereren.
|
maken genereert nieuwe sleutels en is niet de updateroute.
|
||||||
|
|
||||||
Open **ESPHome Device Builder → Secrets** en vul eenmaal je 2,4GHz-wifi in:
|
Wil je ESPHome Device Builder gebruiken, kies dan **Maak installatie-YAML** en
|
||||||
|
kopieer/download die YAML naar een eigen apparaat daar. Beide routes gebruiken
|
||||||
```yaml
|
dezelfde firmwarepakketten. Wifi blijft in ESPHome `secrets.yaml`; API- en
|
||||||
wifi_ssid: "Jouw wifi"
|
OTA-sleutels staan in het eigen apparaatprofiel.
|
||||||
wifi_password: "Jouw wifiwachtwoord"
|
|
||||||
```
|
|
||||||
|
|
||||||
Andere bestaande secrets mogen blijven staan. Gebruik geen gedeelde API-sleutel
|
|
||||||
voor alle nieuwe schermen; de gedownloade YAML bevat al een eigen sleutel.
|
|
||||||
|
|
||||||
## 3. Eerste flash via USB op de Raspberry
|
## 3. Eerste flash via USB op de Raspberry
|
||||||
|
|
||||||
1. Klik in ESPHome op **New device**, gebruik dezelfde unieke naam en sla de
|
1. Sluit het scherm met een **USB-datakabel** aan op de machine waarop Home
|
||||||
directe installatie over. Kies zo nodig ESP32 als tijdelijke wizardkeuze.
|
Assistant draait. Bij meerdere borden: identificeer eerst de juiste poort,
|
||||||
2. Klik **Edit** bij het nieuwe apparaat. Vervang de **hele inhoud** door je
|
of sluit ze voor de eerste installatie één voor één aan.
|
||||||
gedownloade YAML en sla op. Het pakket levert zelf de juiste hardwareconfiguratie.
|
2. Open **Firmware & USB** in ESP Screens en kies het zojuist bewaarde profiel.
|
||||||
3. Sluit het scherm met USB aan op de Raspberry waarop Home Assistant draait.
|
3. Kies bij **Installeren naar** de USB-poort van dit scherm.
|
||||||
4. Klik **Install → Plug into the computer running ESPHome Device Builder**.
|
4. Klik **Bouwen & installeren** en wacht op een geslaagde build én upload.
|
||||||
Kies de USB-seriële poort van dit scherm. Bij meerdere schermen: sluit ze voor
|
De eerste build kan op een Raspberry meerdere minuten duren.
|
||||||
de eerste installatie één voor één aan.
|
5. Het scherm herstart en verbindt met wifi. Latere firmware-updates kunnen via
|
||||||
5. Wacht op een geslaagde build én upload. De eerste build kan op een Raspberry
|
**Wifi / OTA** in dezelfde pagina, met het bestaande profiel.
|
||||||
lang duren. Laat deze afronden. Het scherm maakt daarna verbinding met wifi.
|
|
||||||
|
|
||||||
Een browseroptie **Plug into this computer** bedoelt de computer waarop je browser
|
Een USB-kabel aan je laptop is niet zichtbaar als USB-poort van de Raspberry.
|
||||||
draait, niet de Raspberry. Kies die alleen wanneer het scherm aan die computer zit.
|
Gebruik voor die route de ESPHome-CLI op de laptop met je eigen profiel, of de
|
||||||
|
browserinstallatie van ESPHome Device Builder. De stappen hierboven gebruiken
|
||||||
|
uitsluitend ESP Screens op de HA-machine.
|
||||||
|
|
||||||
**CYD:** bij de eerste start verschijnt de kalibratie. Tik het zichtbare kruisje
|
**CYD:** bij de eerste start verschijnt de kalibratie. Tik het zichtbare kruisje
|
||||||
drie keer rustig aan, houd elke tik kort vast en volg steeds het volgende kruisje.
|
drie keer rustig aan, houd elke tik kort vast en volg steeds het volgende kruisje.
|
||||||
@@ -112,7 +99,9 @@ domeinfilters met gekleurde iconen. Je kunt maximaal twintig tegels toevoegen.
|
|||||||
Het schermvoorbeeld toont hun plaats: twee kolommen, zes tegels per pagina.
|
Het schermvoorbeeld toont hun plaats: twee kolommen, zes tegels per pagina.
|
||||||
Sleep een tegel naar een andere tegel om te ordenen. Klik op een tegel voor
|
Sleep een tegel naar een andere tegel om te ordenen. Klik op een tegel voor
|
||||||
een eigen naam, de pijltjes voor volgorde en **Bediening & weergave instellen**:
|
een eigen naam, de pijltjes voor volgorde en **Bediening & weergave instellen**:
|
||||||
klikgedrag, een mini-slider of een grote waarde waar ondersteund. Een lege
|
klikgedrag, een mini-slider of een grote waarde waar ondersteund. Kies bij
|
||||||
|
**Pastel achtergrond** een eigen kleur met donkere tekst; **Standaard** herstelt
|
||||||
|
de normale weergave. Hiervoor is firmware 0.2.10+ nodig. Een lege
|
||||||
tegel brengt je naar de zoekbalk; toevoegen vult de eerstvolgende vrije positie.
|
tegel brengt je naar de zoekbalk; toevoegen vult de eerstvolgende vrije positie.
|
||||||
Het voorbeeld toont de indeling, geen live sensorwaarden.
|
Het voorbeeld toont de indeling, geen live sensorwaarden.
|
||||||
Klik **Opslaan & naar scherm** om je wijzigingen door te sturen.
|
Klik **Opslaan & naar scherm** om je wijzigingen door te sturen.
|
||||||
@@ -144,7 +133,7 @@ zodra het scherm terugkomt. De app moet blijven draaien voor actuele tegeldata.
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Andere entiteiten, namen of volgorde | Opslaan in ESP Screens | Wifi, sleutels, kalibratie |
|
| Andere entiteiten, namen of volgorde | Opslaan in ESP Screens | Wifi, sleutels, kalibratie |
|
||||||
| Nieuwe beheerpagina/appversie | Appwinkel → ESP Screen Manager → Update | Alle indelingen in `/data/screens.json` |
|
| Nieuwe beheerpagina/appversie | Appwinkel → ESP Screen Manager → Update | Alle indelingen in `/data/screens.json` |
|
||||||
| Nieuwe schermfunctie/kaart | ESPHome → bestaand apparaat → Install → Wirelessly | Eigen YAML, sleutels en CYD-kalibratie; app stuurt tegels opnieuw |
|
| Nieuwe schermfunctie/kaart | Firmware & USB → bestaand profiel → Wifi / OTA | Eigen YAML, sleutels en CYD-kalibratie; app stuurt tegels opnieuw |
|
||||||
|
|
||||||
De eigen YAML verwijst naar de firmwarepakketten in `main`. Bij een nieuwe build
|
De eigen YAML verwijst naar de firmwarepakketten in `main`. Bij een nieuwe build
|
||||||
haalt ESPHome de nieuwste gepubliceerde pakket- en componentcode op. Je vervangt
|
haalt ESPHome de nieuwste gepubliceerde pakket- en componentcode op. Je vervangt
|
||||||
@@ -152,7 +141,7 @@ je eigen YAML dus niet door een nieuw downloadbestand. Wifi, naam en sleutels
|
|||||||
staan buiten het gedeelde pakket en blijven gelijk.
|
staan buiten het gedeelde pakket en blijven gelijk.
|
||||||
|
|
||||||
Maak vóór updates een Home Assistant-back-up inclusief ESP Screen Manager en
|
Maak vóór updates een Home Assistant-back-up inclusief ESP Screen Manager en
|
||||||
ESPHome Device Builder. **Verwijderen/herinstalleren** van een app is niet hetzelfde
|
de eigen ESPHome-configuraties. **Verwijderen/herinstalleren** van een app is niet hetzelfde
|
||||||
als updaten; daarmee kun je de gegevensmap wissen. Houd de apparaatnaam en de
|
als updaten; daarmee kun je de gegevensmap wissen. Houd de apparaatnaam en de
|
||||||
entity-ID van **Tegelinstellingen** gelijk, zodat de bestaande indeling gekoppeld blijft.
|
entity-ID van **Tegelinstellingen** gelijk, zodat de bestaande indeling gekoppeld blijft.
|
||||||
|
|
||||||
@@ -207,7 +196,9 @@ Hierna vragen wijzigingen aan deze instellingen geen nieuwe firmwareflash.
|
|||||||
| Helderheid nacht | 0–100%, maximaal normale helderheid | 10% |
|
| Helderheid nacht | 0–100%, maximaal normale helderheid | 10% |
|
||||||
| Klok tonen | Aan/uit | Aan |
|
| Klok tonen | Aan/uit | Aan |
|
||||||
| Tijdnotatie | 24 of 12 uur, zonder AM/PM | 24 uur |
|
| Tijdnotatie | 24 of 12 uur, zonder AM/PM | 24 uur |
|
||||||
| Terug naar pagina 1 | Bij standby; anders huidige pagina onthouden | Uit |
|
| Terug naar pagina 1 | Sluit ook detailmenu’s bij standby | Uit |
|
||||||
|
| Vegen tussen pagina’s | Native horizontale swipe, firmware 0.2.7+ | Uit |
|
||||||
|
| Guition draaien | 0°, 90°, 180°, 270°, firmware 0.2.9+ | 0° |
|
||||||
|
|
||||||
Nachturen gebruiken de tijdzone van het ESPHome-apparaat en de tijd uit HA.
|
Nachturen gebruiken de tijdzone van het ESPHome-apparaat en de tijd uit HA.
|
||||||
Zonder geldige tijd gebruikt het scherm de gewone standbyhelderheid; gelijke
|
Zonder geldige tijd gebruikt het scherm de gewone standbyhelderheid; gelijke
|
||||||
@@ -226,5 +217,6 @@ Bij oudere firmware toont de beheerpagina dat eerst een update nodig is.
|
|||||||
De tegels blijven bruikbaar. Handmatige YAML-profielen blijven hun substitutions
|
De tegels blijven bruikbaar. Handmatige YAML-profielen blijven hun substitutions
|
||||||
gebruiken; voor beheer via deze app gebruik je het Easy Setup-pakket.
|
gebruiken; voor beheer via deze app gebruik je het Easy Setup-pakket.
|
||||||
|
|
||||||
De gemelde Guition-paneelstrepen worden apart onderzocht. Deze instellingenupdate
|
De huidige Guition gebruikt de native ST7701S-configuratie; zie
|
||||||
wijzigt geen displaytimings of driver en is geen bewezen oplossing voor die strepen.
|
[de hardwarevergelijking](GUITION_FACTORY_REFERENCE.md). Instellingen en
|
||||||
|
tegelkleuren veranderen geen paneeltimings. Controleer beeld en touch fysiek.
|
||||||
|
|||||||
+8
-7
@@ -39,15 +39,16 @@ alleen zichtbaar voor de Guition nadat zijn nieuwe firmware door HA is ontdekt.
|
|||||||
De CYD blijft op zijn bestaande oriëntatie met zijn eigen kalibratie.
|
De CYD blijft op zijn bestaande oriëntatie met zijn eigen kalibratie.
|
||||||
|
|
||||||
Zes tegels van **218 × 108 pixels** per pagina, 12px tussenruimte en een
|
Zes tegels van **218 × 108 pixels** per pagina, 12px tussenruimte en een
|
||||||
aparte navigatiestrook. Vanaf zeven tegels verschijnt pagina twee; tot zes
|
aparte navigatiestrook. In ESP Screen Manager passen twintig tegels op maximaal
|
||||||
verdwijnt de navigatie. Grotere letters, iconen, dimmers en kleurkeuzes; de
|
vier pagina’s; tot zes verdwijnt de navigatie. De huidige interface heeft een
|
||||||
climatekaart heeft een grotere temperatuurweergave. Een egaal blauwgrijze
|
lichtgrijze achtergrond, witte kaarten en gekleurde domeiniconen. Vanaf 0.2.10 kun
|
||||||
achtergrond, duidelijk omlijnde blauwe uitgeschakelde tegels en lichte actieve tegels maken
|
je per tegel een pastel achtergrond kiezen met donkere tekst. Standby begint
|
||||||
de status herkenbaar. Standby begint na tien minuten zonder aanraking.
|
standaard na tien minuten zonder aanraking en is instelbaar in de beheerpagina.
|
||||||
|
|
||||||
De bestaande tegelacties, climatebediening en vacuumkaart zijn behouden.
|
De bestaande tegelacties, climatebediening en vacuumkaart zijn behouden.
|
||||||
De vacuumkaart blijft gekoppeld aan tegel 6. Posities 8/10 zijn eenvoudige
|
Alle kaarttypen zijn beschikbaar op alle twintig runtime-posities. Alleen in
|
||||||
actietegels; zie [TEGELS.md](TEGELS.md) voor de ondersteunde bindingen.
|
het oude handmatige profiel blijft de vacuumkaart op tegel 6 en hebben posities
|
||||||
|
8/10 beperkingen; zie [TEGELS.md](TEGELS.md).
|
||||||
|
|
||||||
## Nieuwe installatie
|
## Nieuwe installatie
|
||||||
|
|
||||||
|
|||||||
@@ -111,3 +111,13 @@ De firmware bewaart de hoek als afzonderlijke uint32 op key `0x524F5431`; de
|
|||||||
bestaande Settings-structuur en CYD-kalibratie blijven ongewijzigd. Alleen de
|
bestaande Settings-structuur en CYD-kalibratie blijven ongewijzigd. Alleen de
|
||||||
Guition activeert de rotatiecallback. De diagnostische entity `Guition schermtype`
|
Guition activeert de rotatiecallback. De diagnostische entity `Guition schermtype`
|
||||||
maakt deze capability herkenbaar, ook als het scherm offline of hernoemd is.
|
maakt deze capability herkenbaar, ook als het scherm offline of hernoemd is.
|
||||||
|
|
||||||
|
### Compatibiliteit 0.2.10
|
||||||
|
|
||||||
|
`tiles[].options.background` is een optionele paletnaam binnen opslagversie 1.
|
||||||
|
Op de draad staat dit in het bestaande `o`-object. Oudere firmware negeert het
|
||||||
|
veld; nieuwe firmware valt bij onbekende namen terug op de normale kleuren.
|
||||||
|
De app accepteert uitsluitend het lichte palet uit `TILE_BACKGROUNDS`. Een oude
|
||||||
|
editor die `background` weglaat behoudt de opgeslagen kleur voor dezelfde entity;
|
||||||
|
expliciet `auto` herstelt de standaard. Geen gewijzigde voorkeurstructuur of
|
||||||
|
sleutels, geen nieuwe firmwareflash nodig voor latere kleurkeuzes.
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# 0.2.10 — pastel tegelkleuren en actuele documentatie
|
||||||
|
|
||||||
|
De editor levert negen lichte kleuren plus Standaard. Dezelfde paletwaarden
|
||||||
|
worden in firmware gebruikt. De gekozen achtergrond blijft vast bij een
|
||||||
|
statuswisseling; iconen, status en actiefeedback blijven de entiteit volgen.
|
||||||
|
Titels zijn bij een eigen kleur donker op zowel Guition als CYD.
|
||||||
|
|
||||||
|
## Uitgevoerd
|
||||||
|
|
||||||
|
- 51 Python-tests geslaagd, inclusief overeenkomst tussen editor- en
|
||||||
|
firmwarepalet, minimaal 7:1 titelcontrast en 4,5:1 statuscontrast, validatie
|
||||||
|
van kleuren en behoud bij appherstart/opslaan vanuit een oude editor.
|
||||||
|
- Alle negen C++-testprogramma's geslaagd; JavaScript-syntax gecontroleerd.
|
||||||
|
- Beide runtimefirmwares gebouwd met ESPHome 2026.6.2 en via OTA op de vooraf
|
||||||
|
geïdentificeerde Guition en CYD gezet. Eigen sleutels en kalibratie behouden.
|
||||||
|
- Ook beide handmatige firmwareprofielen bouwen succesvol.
|
||||||
|
- Op beide schermen met hun bestaande indeling: tien paginacontroles,
|
||||||
|
vijftig overlaycycli en de slidertest geslaagd.
|
||||||
|
- De renderdiagnose controleert bij gekleurde tegels ook de werkelijk
|
||||||
|
toegepaste LVGL-achtergrond en donkere titelkleur.
|
||||||
|
|
||||||
|
De README en Easy Setup beschrijven nu de één-app-route met de ingebouwde
|
||||||
|
ESPHome-CLI. De oude handmatige CYD-route blijft ingeklapt beschikbaar en wordt
|
||||||
|
expliciet onderscheiden van de runtime-indeling met twintig tegels.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
|
# 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.
|
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
|
||||||
substitutions:
|
substitutions:
|
||||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
SCREEN_FIRMWARE_VERSION: "0.2.10"
|
||||||
DYNAMIC_TILES: "false"
|
DYNAMIC_TILES: "false"
|
||||||
DASHBOARD_INBOX_INTERNAL: "true"
|
DASHBOARD_INBOX_INTERNAL: "true"
|
||||||
DEVICE_NAME: "guition-wallbox"
|
DEVICE_NAME: "guition-wallbox"
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
substitutions:
|
substitutions:
|
||||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
SCREEN_FIRMWARE_VERSION: "0.2.10"
|
||||||
DYNAMIC_TILES: "false"
|
DYNAMIC_TILES: "false"
|
||||||
DASHBOARD_INBOX_INTERNAL: "true"
|
DASHBOARD_INBOX_INTERNAL: "true"
|
||||||
DEVICE_NAME: "cyd-new"
|
DEVICE_NAME: "cyd-new"
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@
|
|||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
substitutions:
|
substitutions:
|
||||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
SCREEN_FIRMWARE_VERSION: "0.2.10"
|
||||||
DYNAMIC_TILES: "true"
|
DYNAMIC_TILES: "true"
|
||||||
DASHBOARD_INBOX_INTERNAL: "false"
|
DASHBOARD_INBOX_INTERNAL: "false"
|
||||||
DEVICE_NAME: "cyd-new"
|
DEVICE_NAME: "cyd-new"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
|
# 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.
|
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
|
||||||
substitutions:
|
substitutions:
|
||||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
SCREEN_FIRMWARE_VERSION: "0.2.10"
|
||||||
DYNAMIC_TILES: "true"
|
DYNAMIC_TILES: "true"
|
||||||
DASHBOARD_INBOX_INTERNAL: "false"
|
DASHBOARD_INBOX_INTERNAL: "false"
|
||||||
DEVICE_NAME: "guition-new"
|
DEVICE_NAME: "guition-new"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
## 0.2.10
|
||||||
|
|
||||||
|
- Kies per tegel een pastel achtergrond: rood, oranje, geel, groen, mint, blauw, paars, roze of grijs. Standaard herstelt de normale kleuren. De keuze is zichtbaar in het schermvoorbeeld en werkt met donkere tekst op Guition én CYD.
|
||||||
|
- Tegelkleuren blijven behouden bij appupdates en bij opslaan vanuit een oudere beheerpagina. Installeer firmware 0.2.10 op het scherm om de kleuren weer te geven.
|
||||||
|
- README en Easy Setup beschrijven de huidige één-app-installatie, twintig tegels, inspector, rotatie en updates via de ingebouwde ESPHome-CLI.
|
||||||
|
|
||||||
## 0.2.9
|
## 0.2.9
|
||||||
|
|
||||||
- Guition: kies 0°, 90°, 180° of 270° onder Scherminstellingen. Na opslaan draait de interface direct mee, inclusief touch. De hoek blijft bewaard na herstart; een nieuwe flash per hoek is niet nodig.
|
- Guition: kies 0°, 90°, 180° of 270° onder Scherminstellingen. Na opslaan draait de interface direct mee, inclusief touch. De hoek blijft bewaard na herstart; een nieuwe flash per hoek is niet nodig.
|
||||||
|
|||||||
@@ -10,6 +10,20 @@ REPO = 'https://github.com/MaxGramser/homeassistant_espscreen'
|
|||||||
REFS = {'cyd': 'main', 'guition': 'main'}
|
REFS = {'cyd': 'main', 'guition': 'main'}
|
||||||
ATTRS = frozenset('brightness percentage current_position current_temperature temperature current_humidity min_temp max_temp target_temp_step supported_color_modes hvac_modes 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 media_title options min max step temperature_unit supported_features'.split())
|
ATTRS = frozenset('brightness percentage current_position current_temperature temperature current_humidity min_temp max_temp target_temp_step supported_color_modes hvac_modes 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 media_title options min max step temperature_unit supported_features'.split())
|
||||||
|
|
||||||
|
|
||||||
|
TILE_BACKGROUNDS = {
|
||||||
|
'auto': {'label': 'Standaard', 'color': None},
|
||||||
|
'red': {'label': 'Rood', 'color': '#FADADD'},
|
||||||
|
'orange': {'label': 'Oranje', 'color': '#FFE1C6'},
|
||||||
|
'yellow': {'label': 'Geel', 'color': '#FFF0C2'},
|
||||||
|
'green': {'label': 'Groen', 'color': '#D9EEDC'},
|
||||||
|
'mint': {'label': 'Mint', 'color': '#D5F0EA'},
|
||||||
|
'blue': {'label': 'Blauw', 'color': '#D9EAFB'},
|
||||||
|
'purple': {'label': 'Paars', 'color': '#E9DDF5'},
|
||||||
|
'pink': {'label': 'Roze', 'color': '#F7DDEC'},
|
||||||
|
'gray': {'label': 'Grijs', 'color': '#E5E7EB'},
|
||||||
|
}
|
||||||
|
|
||||||
# Additive schema 1 extension. An absent object retains old firmware/YAML defaults.
|
# Additive schema 1 extension. An absent object retains old firmware/YAML defaults.
|
||||||
SETTING_RULES = {
|
SETTING_RULES = {
|
||||||
'standby_enabled': (True, None, None),
|
'standby_enabled': (True, None, None),
|
||||||
@@ -72,8 +86,10 @@ def validate_layout(data):
|
|||||||
item = {'entity': tile['entity'], 'name': name.strip()}
|
item = {'entity': tile['entity'], 'name': name.strip()}
|
||||||
if 'options' in tile:
|
if 'options' in tile:
|
||||||
options = tile['options']
|
options = tile['options']
|
||||||
if not isinstance(options, dict) or set(options) - {'tap', 'display', 'inline', 'history_hours'}:
|
if not isinstance(options, dict) or set(options) - {'tap', 'display', 'inline', 'history_hours', 'background'}:
|
||||||
raise ValueError('Onbekende tegelinstellingen.')
|
raise ValueError('Onbekende tegelinstellingen.')
|
||||||
|
if 'background' in options and (not isinstance(options['background'],str) or options['background'] not in TILE_BACKGROUNDS):
|
||||||
|
raise ValueError('Kies een pastel achtergrondkleur uit het palet.')
|
||||||
choices = {'tap': ('auto', 'detail', 'toggle', 'none'), 'display': ('standard', 'watch'), 'inline': ('none', 'slider')}
|
choices = {'tap': ('auto', 'detail', 'toggle', 'none'), 'display': ('standard', 'watch'), 'inline': ('none', 'slider')}
|
||||||
domain = tile['entity'].split('.')[0]
|
domain = tile['entity'].split('.')[0]
|
||||||
for key, allowed in choices.items():
|
for key, allowed in choices.items():
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import math
|
|||||||
from firmware import Firmware
|
from firmware import Firmware
|
||||||
|
|
||||||
from aiohttp import ClientSession, ClientTimeout, WSMsgType, web
|
from aiohttp import ClientSession, ClientTimeout, WSMsgType, web
|
||||||
from core import discover, installation_yaml, packets, state_message, validate_layout, validate_settings
|
from core import TILE_BACKGROUNDS, discover, installation_yaml, packets, state_message, validate_layout, validate_settings
|
||||||
|
|
||||||
LOG = logging.getLogger('screen_manager')
|
LOG = logging.getLogger('screen_manager')
|
||||||
|
|
||||||
@@ -191,6 +191,9 @@ class Manager:
|
|||||||
raise ValueError('Rotatie vereist een Guition met firmware 0.2.9 of nieuwer.')
|
raise ValueError('Rotatie vereist een Guition met firmware 0.2.9 of nieuwer.')
|
||||||
old_tiles = {t['entity']:t for t in self.layouts.get(inbox,{}).get('tiles',[])}
|
old_tiles = {t['entity']:t for t in self.layouts.get(inbox,{}).get('tiles',[])}
|
||||||
for tile in layout['tiles']:
|
for tile in layout['tiles']:
|
||||||
|
old_options=old_tiles.get(tile['entity'],{}).get('options',{})
|
||||||
|
if 'options' in tile and 'background' not in tile['options'] and 'background' in old_options:
|
||||||
|
tile['options']['background']=old_options['background']
|
||||||
if 'options' not in tile and 'options' in old_tiles.get(tile['entity'],{}):
|
if 'options' not in tile and 'options' in old_tiles.get(tile['entity'],{}):
|
||||||
tile['options'] = old_tiles[tile['entity']]['options'].copy()
|
tile['options'] = old_tiles[tile['entity']]['options'].copy()
|
||||||
known = {e['id'] for e in self.inventory()[1]}
|
known = {e['id'] for e in self.inventory()[1]}
|
||||||
@@ -320,7 +323,7 @@ def create_app(manager, development=False):
|
|||||||
for screen in screens:
|
for screen in screens:
|
||||||
screen['layout'] = manager.layouts.get(screen['id'], {'title': 'Thuis', 'tiles': []})
|
screen['layout'] = manager.layouts.get(screen['id'], {'title': 'Thuis', 'tiles': []})
|
||||||
screen['delivery'] = manager.status.get(screen['id'], 'Kies je eerste tegels')
|
screen['delivery'] = manager.status.get(screen['id'], 'Kies je eerste tegels')
|
||||||
return web.json_response({'csrf': csrf, 'connected': manager.ha.online, 'screens': screens, 'entities': entities})
|
return web.json_response({'csrf': csrf, 'connected': manager.ha.online, 'screens': screens, 'entities': entities, 'backgrounds': TILE_BACKGROUNDS})
|
||||||
async def save(request):
|
async def save(request):
|
||||||
manager.save(request.match_info['inbox'], await request.json())
|
manager.save(request.match_info['inbox'], await request.json())
|
||||||
return web.json_response({'saved': True})
|
return web.json_response({'saved': True})
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ function renderPreview() {
|
|||||||
const card = node("button", undefined, "preview-tile");
|
const card = node("button", undefined, "preview-tile");
|
||||||
if (tile) {
|
if (tile) {
|
||||||
const name = tile.name || inventory.entities.find(e => e.id === tile.entity)?.name || tile.entity;
|
const name = tile.name || inventory.entities.find(e => e.id === tile.entity)?.name || tile.entity;
|
||||||
|
const background=inventory.backgrounds?.[tile.options?.background]?.color;
|
||||||
|
if(background)card.style.backgroundColor=background;
|
||||||
card.append(domainBadge(tile.entity), node("strong", name));
|
card.append(domainBadge(tile.entity), node("strong", name));
|
||||||
card.draggable = true;
|
card.draggable = true;
|
||||||
card.ondragstart = (e) => { dragIndex = slot; e.dataTransfer.setData("text/plain", String(slot)); };
|
card.ondragstart = (e) => { dragIndex = slot; e.dataTransfer.setData("text/plain", String(slot)); };
|
||||||
@@ -358,6 +360,27 @@ function renderTiles() {
|
|||||||
if (!e.target.closest("input, select, button, summary, .tile-options"))
|
if (!e.target.closest("input, select, button, summary, .tile-options"))
|
||||||
options.open = !options.open;
|
options.open = !options.open;
|
||||||
};
|
};
|
||||||
|
const palette = node("fieldset", undefined, "tile-palette");
|
||||||
|
palette.append(node("legend", "Pastel achtergrond"));
|
||||||
|
const swatches = node("div", undefined, "palette-swatches");
|
||||||
|
for(const [key, choice] of Object.entries(inventory.backgrounds || {})) {
|
||||||
|
const button=node("button", undefined, "palette-choice");
|
||||||
|
button.type="button";
|
||||||
|
button.setAttribute("aria-label", `Achtergrond: ${choice.label}`);
|
||||||
|
button.setAttribute("aria-pressed", String((tile.options?.background || "auto") === key));
|
||||||
|
const sample=node("span", undefined, "palette-sample");
|
||||||
|
if(choice.color)sample.style.backgroundColor=choice.color;
|
||||||
|
else sample.classList.add("palette-auto");
|
||||||
|
button.append(sample,node("span",choice.label));
|
||||||
|
button.onclick=()=>{
|
||||||
|
tile.options={...tile.options,background:key};
|
||||||
|
for(const other of swatches.children)other.setAttribute("aria-pressed",String(other===button));
|
||||||
|
markDirty();renderPreview();
|
||||||
|
};
|
||||||
|
swatches.append(button);
|
||||||
|
}
|
||||||
|
palette.append(swatches,node("small", "Donkere tekst blijft leesbaar. Kies Standaard voor de normale kleuren. Vereist schermfirmware 0.2.10+."));
|
||||||
|
options.append(palette);
|
||||||
const controls = {};
|
const controls = {};
|
||||||
const domain = tile.entity.split(".")[0];
|
const domain = tile.entity.split(".")[0];
|
||||||
const fields = [
|
const fields = [
|
||||||
@@ -803,7 +826,7 @@ async function inspect(entity) {
|
|||||||
card.append(
|
card.append(
|
||||||
node(
|
node(
|
||||||
"small",
|
"small",
|
||||||
`Kleine slider: ${options.inline === "slider" ? "ja" : "nee"} · Weergave: ${options.display === "watch" ? "grote waarde" : "standaard"}`,
|
`Kleine slider: ${options.inline === "slider" ? "ja" : "nee"} · Weergave: ${options.display === "watch" ? "grote waarde" : "standaard"} · Achtergrond: ${inventory.backgrounds?.[options.background || "auto"]?.label || "Standaard"}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$("#inspection-summary").append(card);
|
$("#inspection-summary").append(card);
|
||||||
|
|||||||
@@ -720,3 +720,13 @@ pre {
|
|||||||
#tiles > .selected-tile { background: #f8fafc; border-color: #aac4df; }
|
#tiles > .selected-tile { background: #f8fafc; border-color: #aac4df; }
|
||||||
.picker { position: sticky; top: 16px; }
|
.picker { position: sticky; top: 16px; }
|
||||||
@media (max-width: 800px) { .picker { position: static; } }
|
@media (max-width: 800px) { .picker { position: static; } }
|
||||||
|
|
||||||
|
.tile-palette { margin: 12px 0; padding: 12px; border: 1px solid #d8dfe5; border-radius: 12px; }
|
||||||
|
.tile-palette legend { font-weight: 650; padding: 0 5px; }
|
||||||
|
.palette-swatches { display: grid; grid-template-columns: repeat(auto-fit, minmax(66px, 1fr)); gap: 8px; margin-bottom: 10px; }
|
||||||
|
.palette-choice { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 6px; color: #1b1b1b; background: white; border: 2px solid transparent; border-radius: 10px; font-size: 12px; }
|
||||||
|
.palette-choice[aria-pressed="true"] { border-color: #1674ae; background: #edf6ff; }
|
||||||
|
.palette-choice:focus-visible { outline: 3px solid #1674ae; outline-offset: 2px; }
|
||||||
|
.palette-sample { width: 36px; height: 28px; border-radius: 7px; border: 1px solid #0002; }
|
||||||
|
.palette-auto { background: linear-gradient(135deg, #fff 50%, #e5e7eb 50%); }
|
||||||
|
.tile-palette small { color: #52616e; }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: ESP Screen Manager
|
name: ESP Screen Manager
|
||||||
version: "0.2.9"
|
version: "0.2.10"
|
||||||
slug: esp_screen_manager
|
slug: esp_screen_manager
|
||||||
description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen.
|
description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen.
|
||||||
url: https://github.com/MaxGramser/homeassistant_espscreen
|
url: https://github.com/MaxGramser/homeassistant_espscreen
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "components/smart_display/tile_palette.h"
|
||||||
|
#include <cassert>
|
||||||
|
int main() {
|
||||||
|
assert(tile_palette::color("auto")==0);
|
||||||
|
assert(tile_palette::color("")==0);
|
||||||
|
assert(tile_palette::color("unknown-future-choice")==0);
|
||||||
|
assert(tile_palette::color("red")!=0);
|
||||||
|
assert(tile_palette::color("green")!=tile_palette::color("red"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import re
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
import test_portal
|
||||||
|
from core import TILE_BACKGROUNDS, validate_layout
|
||||||
|
|
||||||
|
def luminance(color):
|
||||||
|
rgb=[int(color[i:i+2],16)/255 for i in (1,3,5)]
|
||||||
|
linear=[v/12.92 if v<=0.04045 else ((v+0.055)/1.055)**2.4 for v in rgb]
|
||||||
|
return sum(v*w for v,w in zip(linear,(.2126,.7152,.0722)))
|
||||||
|
|
||||||
|
class PaletteTests(unittest.IsolatedAsyncioTestCase):
|
||||||
|
def test_palette_matches_firmware_and_has_readable_text(self):
|
||||||
|
header=(Path(__file__).resolve().parents[1]/'components/smart_display/tile_palette.h').read_text()
|
||||||
|
native=dict(re.findall(r'name=="(\w+)"\)return 0x([A-F0-9]+)',header))
|
||||||
|
expected={k:v['color'][1:] for k,v in TILE_BACKGROUNDS.items() if v['color']}
|
||||||
|
self.assertEqual(native,expected)
|
||||||
|
for color in expected.values():
|
||||||
|
for foreground,minimum in (('#1B1B1B',7),('#46525E',4.5)):
|
||||||
|
self.assertGreaterEqual((luminance('#'+color)+.05)/(luminance(foreground)+.05),minimum)
|
||||||
|
|
||||||
|
async def test_old_editor_preserves_color_and_explicit_auto_clears(self):
|
||||||
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
|
m=test_portal.ManagerTests().setup_manager(Path(tmp)/'screens.json')
|
||||||
|
layout={'title':'Thuis','tiles':[{'entity':'light.a','options':{'background':'red','inline':'slider'}}]}
|
||||||
|
m.save('text.screen',layout)
|
||||||
|
m.save('text.screen',{'title':'Nieuw','tiles':[{'entity':'light.a','options':{'inline':'none'}}]})
|
||||||
|
fresh=test_portal.ManagerTests().setup_manager(m.path)
|
||||||
|
tile=fresh.layouts['text.screen']['tiles'][0]
|
||||||
|
self.assertEqual(tile['options'],{'background':'red','inline':'none'})
|
||||||
|
await fresh.sync_one('text.screen',fresh.layouts['text.screen'])
|
||||||
|
self.assertEqual(fresh.ha.messages[1][1]['o']['background'],'red')
|
||||||
|
fresh.save('text.screen',{'title':'Nieuw','tiles':[{'entity':'light.a','options':{'background':'auto'}}]})
|
||||||
|
self.assertEqual(fresh.layouts['text.screen']['tiles'][0]['options']['background'],'auto')
|
||||||
|
|
||||||
|
def test_unapproved_colors_rejected(self):
|
||||||
|
for value in ('#000000','url(test)','unknown',None,{},42):
|
||||||
|
with self.assertRaises(ValueError):validate_layout({'title':'Thuis','tiles':[{'entity':'light.a','options':{'background':value}}]})
|
||||||
Reference in New Issue
Block a user