From ad8a8ccf56517a22d440a1afe2ba672fd7006691 Mon Sep 17 00:00:00 2001 From: Max Gramser Date: Sat, 19 Sep 2026 16:08:01 +0200 Subject: [PATCH] Let the screen list see the Screen language sensor, so a language update is confirmed and not offered again The cached screen list only read the entities named in SCREEN_ENTITY_NAMES, which lacked the new sensor: the updater waited in vain after a language update, the live page kept offering it, and the nightly round would have rebuilt the screen every night. Found in the end-to-end test. Co-Authored-By: Claude Opus 5 --- screen_manager/app/core.py | 3 ++- tests/test_updates.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/screen_manager/app/core.py b/screen_manager/app/core.py index b67b5b8..6726698 100644 --- a/screen_manager/app/core.py +++ b/screen_manager/app/core.py @@ -200,7 +200,8 @@ NAME_DEVICE_NAME = ('Device name', 'Apparaatnaam') NAME_IP_ADDRESS = ('IP address', 'IP-adres') # The language a screen's firmware was built in (firmware 0.2.76+, app 0.2.90); older firmware speaks English. NAME_SCREEN_LANGUAGE = ('Screen language',) -SCREEN_ENTITY_NAMES = frozenset(NAME_TILE_SETTINGS + NAME_SCREEN_FIRMWARE + NAME_GUITION_TYPE + NAME_DEVICE_NAME + NAME_IP_ADDRESS) +SCREEN_ENTITY_NAMES = frozenset(NAME_TILE_SETTINGS + NAME_SCREEN_FIRMWARE + NAME_GUITION_TYPE + NAME_DEVICE_NAME + NAME_IP_ADDRESS + + NAME_SCREEN_LANGUAGE) def parse_firmware(text): """(major, minor, patch) of a screen firmware version such as "0.2.63"; None for anything else. Strict on purpose: diff --git a/tests/test_updates.py b/tests/test_updates.py index 0b77413..5646031 100644 --- a/tests/test_updates.py +++ b/tests/test_updates.py @@ -198,6 +198,32 @@ class UpdaterTests(unittest.IsolatedAsyncioTestCase): self.assertIn(FIRMWARE_VERSION, m.updates.results['text.screen1']['message']) m.firmware.run = original + async def test_language_update_is_verified_by_the_screen_language(self): + """A screen on the current firmware that speaks another language than Settings -> Language & region gets an + update, and the update counts once its "Screen language" sensor says the new language (app 0.2.90). The cached + screen list must see that sensor: without it the check waited in vain and every night rebuilt the screen.""" + with tempfile.TemporaryDirectory() as tmp: + m = self.setup_manager(tmp) + m.ha.registry = m.ha.registry + [{'entity_id': 'sensor.lang1', 'platform': 'esphome', 'original_name': 'Screen language', + 'device_id': 'd1'}] + m.ha.states.update({'text.fw1': {'state': FIRMWARE_VERSION}, 'sensor.lang1': {'state': 'en'}}) + m.ha.ha_language = 'nl' + first = m.screen('text.screen1') + self.assertEqual(first['language'], 'en') + self.assertEqual(m.updates.state_for(first)['language'], True) + self.assertIn('sensor.lang1', m.watched_entities()) + self.assertEqual(m.updates.pending(), ['text.screen1']) + async def speaks_dutch(data): + await asyncio.sleep(0) + m.ha.states['sensor.lang1'] = {'state': 'nl'} + m.firmware.job['state'] = 'success' + m.firmware.run = speaks_dutch + m.updates.start('text.screen1') + await m.updates.task + self.assertEqual(m.updates.results['text.screen1']['state'], 'success') + self.assertEqual(m.screen('text.screen1')['language'], 'nl') + self.assertEqual(m.updates.pending(), []) + async def test_nightly_window_and_persistence(self): with tempfile.TemporaryDirectory() as tmp: m = self.setup_manager(tmp)