Add persistent native Guition rotation to screen settings
This commit is contained in:
@@ -15,6 +15,9 @@ namespace runtime_tiles {
|
||||
inline bool enabled = false;
|
||||
inline bool light_theme = false;
|
||||
inline bool swipe_pages = false;
|
||||
inline uint32_t rotation = 0;
|
||||
inline bool rotation_supported = false;
|
||||
inline esphome::ESPPreferenceObject rotation_preference;
|
||||
inline esphome::ESPPreferenceObject swipe_preference;
|
||||
inline Model model;
|
||||
inline std::string inbox;
|
||||
@@ -30,6 +33,11 @@ inline void load_settings() {
|
||||
swipe_preference = esphome::global_preferences->make_preference<uint32_t>(0x53575031);
|
||||
uint32_t swipe_saved=0;
|
||||
if(swipe_preference.load(&swipe_saved))swipe_pages=swipe_saved==1;
|
||||
if(rotation_supported){
|
||||
rotation_preference=esphome::global_preferences->make_preference<uint32_t>(0x524F5431);
|
||||
uint32_t saved=0;
|
||||
if(rotation_preference.load(&saved) && saved<=270 && saved%90==0)rotation=saved;
|
||||
}
|
||||
screen_settings::Settings saved;
|
||||
if (settings_preference.load(&saved) && saved.valid()) screen_settings::current = saved;
|
||||
}
|
||||
@@ -94,17 +102,24 @@ inline std::string receive(const std::string &payload) {
|
||||
entities.push_back(entity.as<std::string>());
|
||||
}
|
||||
if(!root["swipe_pages"].isNull() && !root["swipe_pages"].is<bool>())return false;
|
||||
if(!root["rotation"].isNull() && (!root["rotation"].is<unsigned>() ||
|
||||
root["rotation"].as<unsigned>()>270 || root["rotation"].as<unsigned>()%90!=0))return false;
|
||||
inbox = string(root["inbox"], 160);
|
||||
bool changed = false;
|
||||
if (!model.set_layout(entities, string(root["title"], 96), changed)) return false;
|
||||
if(root["swipe_pages"].is<bool>() && swipe_pages!=root["swipe_pages"].as<bool>()){
|
||||
swipe_pages=root["swipe_pages"].as<bool>();uint32_t saved=swipe_pages?1:0;swipe_preference.save(&saved);
|
||||
}
|
||||
bool rotation_changed=false;
|
||||
if(rotation_supported && root["rotation"].is<unsigned>() && rotation!=root["rotation"].as<unsigned>()){
|
||||
rotation=root["rotation"].as<unsigned>();rotation_preference.save(&rotation);rotation_changed=true;
|
||||
}
|
||||
if (!(settings == screen_settings::current)) {
|
||||
screen_settings::current = settings;
|
||||
settings_preference.save(&settings); // ESPHome batches flash writes; no write on keepalive.
|
||||
if (settings_changed) settings_changed();
|
||||
rotation_changed=true;
|
||||
}
|
||||
if(rotation_changed && settings_changed)settings_changed();
|
||||
if (changed) { active_index = -1; for (auto &w : widgets) w.cached_active = -1; if (dismiss) dismiss(); }
|
||||
last_received = esphome::millis();
|
||||
if (layout_changed) layout_changed();
|
||||
|
||||
@@ -24,6 +24,20 @@ geen `calibration.yaml` of XPT2046-correctie over.
|
||||
|
||||
## Interface
|
||||
|
||||
### Montage en schermrotatie (runtime 0.2.9+)
|
||||
|
||||
Installeer Guition-firmware 0.2.9 en ESP Screen Manager 0.2.9. Open het scherm
|
||||
in de beheerpagina, ga naar **Scherminstellingen** en kies bij **Scherm draaien**
|
||||
0°, 90°, 180° of 270°, met de klok mee. Klik op opslaan. Een firmwareflash is
|
||||
daarna niet meer nodig om de hoek te wijzigen. De instelling blijft in de appdata
|
||||
en op het scherm bewaard na een herstart.
|
||||
|
||||
Dit gebruikt de native ESPHome/LVGL-rotatie voor beeld én touch, zonder wijzigingen
|
||||
aan de paneelinitialisatie of GT911-spiegeling. Controleer na montage de vier
|
||||
hoeken en de navigatie fysiek; een renderproef test geen aanrakingen. De optie is
|
||||
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.
|
||||
|
||||
Zes tegels van **218 × 108 pixels** per pagina, 12px tussenruimte en een
|
||||
aparte navigatiestrook. Vanaf zeven tegels verschijnt pagina twee; tot zes
|
||||
verdwijnt de navigatie. Grotere letters, iconen, dimmers en kleurkeuzes; de
|
||||
|
||||
@@ -101,3 +101,13 @@ breng de indeling eerst terug tot tien of herstel hun gegevensback-up bij rollba
|
||||
`settings.swipe_pages` is additief in opslagversie 1. Op de draad staat het buiten
|
||||
het ongewijzigde elfvelden-settingsobject. De bestaande preferences blijven gelijk;
|
||||
alleen swipe gebruikt een nieuwe eigen uint32-key `0x53575031`, standaard uit.
|
||||
|
||||
### Compatibiliteit 0.2.9
|
||||
|
||||
Guition-rotatie is additief als `settings.rotation` in appdata, uitsluitend
|
||||
0/90/180/270. Oude beheerpagina's die het veld weglaten behouden de opgeslagen
|
||||
hoek. Op de draad staat `rotation` naast het ongewijzigde elfvelden-settingsobject.
|
||||
De firmware bewaart de hoek als afzonderlijke uint32 op key `0x524F5431`; de
|
||||
bestaande Settings-structuur en CYD-kalibratie blijven ongewijzigd. Alleen de
|
||||
Guition activeert de rotatiecallback. De diagnostische entity `Guition schermtype`
|
||||
maakt deze capability herkenbaar, ook als het scherm offline of hernoemd is.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# 0.2.9 — Guition-rotatie
|
||||
|
||||
De beheerpagina biedt kwartslagen voor de Guition. De native ESPHome 2026.6.2
|
||||
LVGL-component draait beeld en touch samen. De paneelinitialisatie, GT911-transform
|
||||
en CYD-kalibratie zijn niet aangepast. De aparte opgeslagen hoek verandert de
|
||||
bestaande settingsstructuur en preference-keys niet.
|
||||
|
||||
- 48 Python-tests geslaagd, inclusief ongeldige hoeken, behoud na appherstart en
|
||||
opslaan vanuit een oude browser, bordherkenning bij offline status en behoud
|
||||
van het elfvelden-wireprotocol.
|
||||
- Alle acht C++-testprogramma's geslaagd; JavaScript-syntax gecontroleerd.
|
||||
- Beide runtime- en beide handmatige firmwareprofielen gebouwd.
|
||||
- Guition-runtime op het geïdentificeerde apparaat via OTA geïnstalleerd.
|
||||
- Renderdiagnose na opdrachten voor 0°, 90°, 180° en 270°: per stand tien
|
||||
paginacontroles en vijftig overlaycycli geslaagd. Deze controle bedient geen
|
||||
HA-apparaten en is geen fysieke touchmeting.
|
||||
|
||||
De definitieve Guition-build bevat daarnaast een uitlezing van de gewenste én
|
||||
werkelijk door LVGL gebruikte hoek via `ui_state`. Na de definitieve OTA-flash
|
||||
en herstart meldden beide 270°: de voorkeur bleef behouden en werd toegepast.
|
||||
Daarna is de testhoek weer naar 0° teruggezet. Fysieke touchacceptatie is
|
||||
afzonderlijk nodig; de bestaande `tools/verify_gt911.py --rotation` ondersteunt
|
||||
alle vier de hoeken.
|
||||
+14
-1
@@ -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.8"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
||||
DYNAMIC_TILES: "false"
|
||||
DASHBOARD_INBOX_INTERNAL: "true"
|
||||
DEVICE_NAME: "guition-wallbox"
|
||||
@@ -617,6 +617,7 @@ esphome:
|
||||
runtime_tiles::watch_font = id(headline)->get_lv_font();
|
||||
runtime_tiles::enabled = std::string("${DYNAMIC_TILES}") == "true";
|
||||
if (!runtime_tiles::enabled) return;
|
||||
runtime_tiles::rotation_supported = true;
|
||||
runtime_tiles::load_settings();
|
||||
runtime_tiles::settings_changed = []() { id(apply_screen_settings).execute(); };
|
||||
runtime_tiles::dismiss = []() {
|
||||
@@ -778,6 +779,7 @@ api:
|
||||
(unsigned)(millis() - id(last_touch_ms)), id(display_dimmed));
|
||||
ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page),
|
||||
runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN));
|
||||
ESP_LOGI("ui_diag", "rotation=%u actual=%u", (unsigned)runtime_tiles::rotation, (unsigned)id(screen_lvgl).get_rotation());
|
||||
lv_area_t nav, grid;
|
||||
lv_obj_update_layout(id(home_page)->obj);
|
||||
lv_obj_get_coords(id(page_next), &nav);
|
||||
@@ -1334,6 +1336,11 @@ binary_sensor:
|
||||
# - Used by the UI to display fan presets when applicable
|
||||
# ----------------------------------------------------------
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "Guition schermtype"
|
||||
entity_category: diagnostic
|
||||
update_interval: never
|
||||
lambda: 'return {"guition"};'
|
||||
- platform: template
|
||||
name: "Schermfirmware"
|
||||
entity_category: diagnostic
|
||||
@@ -1683,6 +1690,7 @@ display:
|
||||
|
||||
|
||||
lvgl:
|
||||
id: screen_lvgl
|
||||
on_draw_start:
|
||||
- lambda: 'id(rendered_frames)++;'
|
||||
displays:
|
||||
@@ -4546,6 +4554,11 @@ script:
|
||||
then:
|
||||
- lambda: |-
|
||||
const auto &settings = screen_settings::current;
|
||||
if(runtime_tiles::enabled && static_cast<unsigned>(id(screen_lvgl).get_rotation())!=runtime_tiles::rotation){
|
||||
cyd::touch_guard.consume();
|
||||
if(lv_indev_get_act())lv_indev_wait_release(lv_indev_get_act());
|
||||
id(screen_lvgl).set_rotation(static_cast<esphome::display::DisplayRotation>(runtime_tiles::rotation));
|
||||
}
|
||||
if (id(display_dimmed) && !settings.standby_enabled) {
|
||||
id(display_dimmed) = false;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.8"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
||||
DYNAMIC_TILES: "false"
|
||||
DASHBOARD_INBOX_INTERNAL: "true"
|
||||
DEVICE_NAME: "cyd-new"
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.8"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
||||
DYNAMIC_TILES: "true"
|
||||
DASHBOARD_INBOX_INTERNAL: "false"
|
||||
DEVICE_NAME: "cyd-new"
|
||||
|
||||
+14
-1
@@ -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.8"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.9"
|
||||
DYNAMIC_TILES: "true"
|
||||
DASHBOARD_INBOX_INTERNAL: "false"
|
||||
DEVICE_NAME: "guition-new"
|
||||
@@ -621,6 +621,7 @@ esphome:
|
||||
runtime_tiles::watch_font = id(headline)->get_lv_font();
|
||||
runtime_tiles::enabled = std::string("${DYNAMIC_TILES}") == "true";
|
||||
if (!runtime_tiles::enabled) return;
|
||||
runtime_tiles::rotation_supported = true;
|
||||
runtime_tiles::load_settings();
|
||||
runtime_tiles::settings_changed = []() { id(apply_screen_settings).execute(); };
|
||||
runtime_tiles::dismiss = []() {
|
||||
@@ -782,6 +783,7 @@ api:
|
||||
(unsigned)(millis() - id(last_touch_ms)), id(display_dimmed));
|
||||
ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page),
|
||||
runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN));
|
||||
ESP_LOGI("ui_diag", "rotation=%u actual=%u", (unsigned)runtime_tiles::rotation, (unsigned)id(screen_lvgl).get_rotation());
|
||||
lv_area_t nav, grid;
|
||||
lv_obj_update_layout(id(home_page)->obj);
|
||||
lv_obj_get_coords(id(page_next), &nav);
|
||||
@@ -1287,6 +1289,11 @@ binary_sensor:
|
||||
# - Used by the UI to display fan presets when applicable
|
||||
# ----------------------------------------------------------
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "Guition schermtype"
|
||||
entity_category: diagnostic
|
||||
update_interval: never
|
||||
lambda: 'return {"guition"};'
|
||||
- platform: template
|
||||
name: "Schermfirmware"
|
||||
entity_category: diagnostic
|
||||
@@ -1616,6 +1623,7 @@ display:
|
||||
|
||||
|
||||
lvgl:
|
||||
id: screen_lvgl
|
||||
on_draw_start:
|
||||
- lambda: 'id(rendered_frames)++;'
|
||||
displays:
|
||||
@@ -4479,6 +4487,11 @@ script:
|
||||
then:
|
||||
- lambda: |-
|
||||
const auto &settings = screen_settings::current;
|
||||
if(runtime_tiles::enabled && static_cast<unsigned>(id(screen_lvgl).get_rotation())!=runtime_tiles::rotation){
|
||||
cyd::touch_guard.consume();
|
||||
if(lv_indev_get_act())lv_indev_wait_release(lv_indev_get_act());
|
||||
id(screen_lvgl).set_rotation(static_cast<esphome::display::DisplayRotation>(runtime_tiles::rotation));
|
||||
}
|
||||
if (id(display_dimmed) && !settings.standby_enabled) {
|
||||
id(display_dimmed) = false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## 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.
|
||||
- Installeer eerst Guition-firmware 0.2.9 voor deze optie. De CYD behoudt zijn vaste oriëntatie en kalibratie.
|
||||
|
||||
## 0.2.8
|
||||
|
||||
- Firmware: vaste tekstbreedtes voor nette afkapping met puntjes. Ondertitels gebruiken de beschikbare ruimte, ook bij korte titels.
|
||||
|
||||
@@ -24,6 +24,7 @@ SETTING_RULES = {
|
||||
'clock_24h': (True, None, None),
|
||||
'home_on_standby': (False, None, None),
|
||||
'swipe_pages': (False, None, None),
|
||||
'rotation': (0, 0, 270),
|
||||
}
|
||||
|
||||
def validate_settings(data):
|
||||
@@ -36,6 +37,7 @@ def validate_settings(data):
|
||||
valid = type(value) is bool
|
||||
else:
|
||||
valid = type(value) is int and minimum <= value <= maximum
|
||||
if key == "rotation": valid = valid and value in (0, 90, 180, 270)
|
||||
if not valid:
|
||||
raise ValueError(f'Ongeldige waarde voor {key}.')
|
||||
clean[key] = value
|
||||
@@ -129,6 +131,8 @@ def discover(registry, states, devices, areas):
|
||||
area_map = {a['area_id']: a['name'] for a in areas}
|
||||
versions = {item.get('device_id'): states.get(item['entity_id'], {}).get('state', 'onbekend') for item in registry
|
||||
if item.get('platform') == 'esphome' and item.get('original_name') == 'Schermfirmware'}
|
||||
boards = {item.get("device_id"): "guition" for item in registry
|
||||
if item.get("platform") == "esphome" and item.get("original_name") == "Guition schermtype"}
|
||||
screens, entities = [], []
|
||||
for item in registry:
|
||||
eid = item['entity_id']
|
||||
@@ -138,6 +142,7 @@ def discover(registry, states, devices, areas):
|
||||
if item.get('platform') == 'esphome' and eid.startswith('text.') and item.get('original_name') == 'Tegelinstellingen' and not item.get('disabled_by'):
|
||||
screens.append({'id': eid, 'name': device.get('name_by_user') or device.get('name') or eid,
|
||||
'firmware': versions.get(item.get('device_id'), 'onbekend'),
|
||||
'board': boards.get(item.get('device_id'), 'unknown'),
|
||||
'area': area, 'online': state.get('state') not in (None, 'unknown', 'unavailable'),
|
||||
'status': state.get('state', 'Niet verbonden')})
|
||||
if not entity_id(eid) or item.get('disabled_by'):
|
||||
|
||||
@@ -184,6 +184,11 @@ class Manager:
|
||||
layout['settings'] = self.layouts[inbox]['settings'].copy()
|
||||
if 'settings' in layout and 'swipe_pages' not in data.get('settings',{}):
|
||||
layout['settings']['swipe_pages']=self.layouts.get(inbox,{}).get('settings',{}).get('swipe_pages',False)
|
||||
if 'settings' in layout and 'rotation' not in data.get('settings',{}):
|
||||
layout['settings']['rotation']=self.layouts.get(inbox,{}).get('settings',{}).get('rotation',0)
|
||||
screen=next(s for s in self.inventory()[0] if s['id']==inbox)
|
||||
if layout.get('settings',{}).get('rotation',0) and screen.get('board')!='guition':
|
||||
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',[])}
|
||||
for tile in layout['tiles']:
|
||||
if 'options' not in tile and 'options' in old_tiles.get(tile['entity'],{}):
|
||||
@@ -211,8 +216,10 @@ class Manager:
|
||||
return
|
||||
messages = [{'v': 1, 'op': 'layout', 'inbox': inbox, 'title': layout['title'], 'entities': [t['entity'] for t in layout['tiles']]}]
|
||||
if 'settings' in layout:
|
||||
messages[0]['settings'] = {k:v for k,v in layout['settings'].items() if k!='swipe_pages'}
|
||||
messages[0]['settings'] = {k:v for k,v in layout['settings'].items() if k not in ('swipe_pages','rotation')}
|
||||
messages[0]['swipe_pages'] = layout['settings'].get('swipe_pages',False)
|
||||
if next((s.get('board') for s in self.inventory()[0] if s['id']==inbox),None)=='guition':
|
||||
messages[0]['rotation'] = layout['settings'].get('rotation',0)
|
||||
for i,tile in enumerate(layout['tiles']):
|
||||
message=state_message(i,tile,self.ha.states)
|
||||
if tile['entity'].startswith('sensor.') and hasattr(self.ha,'history'):
|
||||
|
||||
@@ -81,6 +81,7 @@ const settingDefinitions = [
|
||||
["show_clock", "Klok tonen", "check", true],
|
||||
["clock_24h", "24-uursklok (uit = 12 uur)", "check", true],
|
||||
["home_on_standby", "Na standby terug naar pagina 1", "check", false],
|
||||
["rotation", "Scherm draaien (met de klok mee)", "rotation", 0],
|
||||
["swipe_pages", "Vegen tussen pagina’s (firmware 0.2.7+)", "check", false],
|
||||
];
|
||||
function renderSettings() {
|
||||
@@ -93,20 +94,25 @@ function renderSettings() {
|
||||
const container = $("#settings-fields");
|
||||
container.replaceChildren();
|
||||
for (const [key, title, kind, , min, max] of settingDefinitions) {
|
||||
if(key === "rotation" && inventory.screens.find(s => s.id === selected)?.board !== "guition") continue;
|
||||
const label = node(
|
||||
"label",
|
||||
undefined,
|
||||
`setting ${kind === "check" ? "setting-check" : ""}`,
|
||||
);
|
||||
const caption = node("span", title),
|
||||
input = node("input"),
|
||||
input = node(kind === "rotation" ? "select" : "input"),
|
||||
output = node("output");
|
||||
input.id = `setting-${key}`;
|
||||
input.type =
|
||||
if(kind !== "rotation") input.type =
|
||||
kind === "check" ? "checkbox" : kind === "minutes" ? "number" : kind;
|
||||
input.setAttribute("aria-label", title);
|
||||
input.required = kind === "minutes" || kind === "time";
|
||||
if (kind === "check") input.checked = values[key];
|
||||
if(kind === "rotation") {
|
||||
for(const angle of [0,90,180,270]) { const option=node("option", `${angle}°`); option.value=angle; input.append(option); }
|
||||
input.value=values[key];
|
||||
}
|
||||
else if (kind === "check") input.checked = values[key];
|
||||
else if (kind === "time")
|
||||
input.value = `${String(Math.floor(values[key] / 60)).padStart(2, "0")}:${String(values[key] % 60).padStart(2, "0")}`;
|
||||
else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: ESP Screen Manager
|
||||
version: "0.2.8"
|
||||
version: "0.2.9"
|
||||
slug: esp_screen_manager
|
||||
description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen.
|
||||
url: https://github.com/MaxGramser/homeassistant_espscreen
|
||||
|
||||
@@ -122,11 +122,11 @@ class ManagerTests(unittest.IsolatedAsyncioTestCase):
|
||||
with self.assertRaises(ValueError): fresh.save('text.screen',{**saved,'settings':{'brightness':0}})
|
||||
self.assertEqual(path.read_bytes(),before)
|
||||
await fresh.sync_one('text.screen',saved)
|
||||
self.assertEqual(fresh.ha.messages[0][1]['settings'],{k:v for k,v in settings.items() if k!='swipe_pages'})
|
||||
self.assertEqual(fresh.ha.messages[0][1]['settings'],{k:v for k,v in settings.items() if k not in ('swipe_pages','rotation')})
|
||||
await fresh.sync_one('text.screen',saved)
|
||||
self.assertEqual(len(fresh.ha.messages),2)
|
||||
await fresh.sync_one('text.screen',saved,True)
|
||||
self.assertEqual(fresh.ha.messages[2][1]['settings'],{k:v for k,v in settings.items() if k!='swipe_pages'})
|
||||
self.assertEqual(fresh.ha.messages[2][1]['settings'],{k:v for k,v in settings.items() if k not in ('swipe_pages','rotation')})
|
||||
|
||||
async def test_reorder_aborts_old_batch(self):
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
import test_portal
|
||||
from core import validate_settings
|
||||
|
||||
class RotationTests(unittest.IsolatedAsyncioTestCase):
|
||||
def test_only_quarter_turns(self):
|
||||
for angle in (0,90,180,270):
|
||||
self.assertEqual(validate_settings({'rotation':angle})['rotation'],angle)
|
||||
for angle in (-90,45,360,True,90.0,'90'):
|
||||
with self.assertRaises(ValueError):validate_settings({'rotation':angle})
|
||||
|
||||
async def test_legacy_wire_and_saved_rotation_survive_old_browser(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
m=test_portal.ManagerTests().setup_manager(Path(tmp)/'screens.json')
|
||||
layout={'title':'Thuis','tiles':[{'entity':'light.a'}],'settings':{'rotation':90}}
|
||||
with self.assertRaises(ValueError):m.save('text.screen',layout)
|
||||
m.ha.registry[0]['device_id']='guition'
|
||||
m.ha.registry.append({'entity_id':'sensor.board','device_id':'guition','platform':'esphome','original_name':'Guition schermtype'})
|
||||
# Capability stays discoverable with the panel offline or renamed.
|
||||
m.ha.states['sensor.board']={'state':'unavailable'}
|
||||
m.save('text.screen',layout)
|
||||
await m.sync_one('text.screen',m.layouts['text.screen'])
|
||||
wire=m.ha.messages[0][1]
|
||||
self.assertEqual(wire['rotation'],90)
|
||||
self.assertEqual(len(wire['settings']),11)
|
||||
self.assertNotIn('rotation',wire['settings'])
|
||||
m.save('text.screen',{'title':'Anders','tiles':layout['tiles'],'settings':{'brightness':80}})
|
||||
self.assertEqual(m.layouts['text.screen']['settings']['rotation'],90)
|
||||
fresh=test_portal.ManagerTests().setup_manager(m.path)
|
||||
self.assertEqual(fresh.layouts['text.screen']['settings']['rotation'],90)
|
||||
Reference in New Issue
Block a user