Make daily traffic scale to dozens of screens: incremental sync, ping keepalive, one action per message (0.2.39)

App 0.2.39 / firmware 0.2.33, items 1, 2, 4, 5 and 6 of the 30-screen scaling check.

- Only the tiles (and top bar) of changed entities are rebuilt; the screen list is
  cached until the registry or a screen diagnostic changes; the SSE stream follows.
- Sensor history comes from one recorder/statistics_during_period call per window in
  a background task, with the REST history as fallback per sensor without statistics.
- Firmware 0.2.33 answers a keepalive ping with its layout revision; a mismatch or a
  restart asks for the layout again, everything is repeated hourly as a safety net.
- The screen_message API action takes one whole message; the text inbox chunks stay
  as fallback for older firmware. A repeated unchanged layout keeps the inbox state.
- Quiet diagnostics: Opgestart (uptime as timestamp) replaces Uptime, heap every
  5 min, setting numbers publish only on change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-14 21:06:45 +02:00
parent 3f6889f750
commit f60eed3ff6
18 changed files with 990 additions and 147 deletions
+2 -2
View File
@@ -81,7 +81,7 @@ class ManagerTests(unittest.IsolatedAsyncioTestCase):
states={'text.screen':{'state':'Ready'},'light.a':{'state':'on','attributes':{'friendly_name':'Lamp'}}}
changed=asyncio.Event()
def __init__(self): self.messages=[]
async def send(self,inbox,message): self.messages.append((inbox,message))
async def send(self,inbox,message,action=None): self.messages.append((inbox,message))
return Manager(HA(),path)
async def test_update_restart_preserves_layout(self):
@@ -136,7 +136,7 @@ class ManagerTests(unittest.IsolatedAsyncioTestCase):
m=self.setup_manager(Path(temp)/'screens.json');layout={'title':'Thuis','tiles':[{'entity':'light.a','name':''}]}
m.save('text.screen',layout)
original=m.ha.send
async def interrupt(inbox,message):
async def interrupt(inbox,message,action=None):
await original(inbox,message)
m.save(inbox,{'title':'Leeg','tiles':[]})
m.ha.send=interrupt