Push inventory over server-sent events and log why the HA websocket closes (0.2.21)

/api/events streams the light inventory whenever the sync loop or a save
changes it (3 s check during firmware updates). The page stops polling
while the stream is open and falls back to the 10 s poll otherwise. The
websocket close is logged with duration, close code and exception.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-13 11:30:46 +02:00
parent 8dc5e616f5
commit 359c289feb
5 changed files with 95 additions and 9 deletions
+22 -3
View File
@@ -1017,18 +1017,37 @@ window.addEventListener("beforeunload", (e) => {
});
refresh();
// Poll only while the tab is visible; a hidden tab would otherwise keep the add-on busy.
let pollTimer, lastFull = Date.now();
// Live updates arrive over server-sent events; polling is the fallback while the stream is down,
// plus a full catalogue refresh every 5 minutes.
let pollTimer, lastFull = Date.now(), live = false, stream;
function applyLive(data) {
inventory = { ...inventory, ...data };
$("#connection").textContent = inventory.connected ? "● Home Assistant verbonden" : "Verbinding met Home Assistant herstellen…";
$("#connection").classList.toggle("online", inventory.connected);
renderScreens();
if (selected) renderSettingsSupport();
if (!selected && inventory.screens.length) select(inventory.screens[0].id);
}
function listen() {
if (stream || typeof EventSource === "undefined") return;
stream = new EventSource("api/events");
stream.onopen = () => { live = true; poll(); };
stream.onmessage = (e) => { if (!document.hidden) applyLive(JSON.parse(e.data)); };
stream.onerror = () => { live = false; poll(); };
}
function poll() {
clearTimeout(pollTimer);
const wait = live ? 60000 : inventory.updates?.busy ? 3000 : 10000;
pollTimer = setTimeout(async () => {
if (!document.hidden) {
const full = Date.now() - lastFull >= 300000;
if (full) lastFull = Date.now();
await refresh(full);
if (full || !live) await refresh(full);
}
poll();
}, inventory.updates?.busy ? 3000 : 10000);
}, wait);
}
listen();
poll();
document.addEventListener("visibilitychange", async () => {
if (document.hidden) return;