From 76b67d347035134ff30638631a3cdf30868b7b8f Mon Sep 17 00:00:00 2001 From: jessikitty Date: Fri, 15 May 2026 16:11:44 +1000 Subject: [PATCH] Fix connection timeout: use REST API for initial state load, increase WS timeout to 60s Large HA instances with many entities cause get_states to exceed the 12s WebSocket timeout. Now loads all states via /api/states HTTP endpoint first (much more reliable for large payloads), with WebSocket get_states as fallback. Also bumped WS send timeout from 12s to 60s for slow HA responses. --- www/parental_controls.html | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/www/parental_controls.html b/www/parental_controls.html index 2e68cc5..f6582f4 100644 --- a/www/parental_controls.html +++ b/www/parental_controls.html @@ -248,17 +248,30 @@ function dispatch(msg) { function send(msg) { return new Promise((res, rej) => { const id = wsId++; msg.id = id; pending[id] = { res, rej }; - setTimeout(() => { if (pending[id]) { delete pending[id]; rej(new Error('timeout')); } }, 12000); + setTimeout(() => { if (pending[id]) { delete pending[id]; rej(new Error('timeout')); } }, 60000); ws.send(JSON.stringify(msg)); }); } + async function onAuth() { setBadge('connected'); - const r = await send({ type: 'get_states' }); - r.result.forEach(s => { states[s.entity_id] = s; }); - await send({ type: 'subscribe_events', event_type: 'state_changed' }); - parseCfg(states[CFG_ENTITY]?.state); render(); + // Use REST API for initial state load — handles large HA instances better + // than WebSocket get_states which can timeout with hundreds of entities + try { + const resp = await fetch(`${prefs.url}/api/states`, { + headers: { Authorization: `Bearer ${prefs.token}` } + }); + if (resp.ok) { const all = await resp.json(); all.forEach(s => { states[s.entity_id] = s; }); } + } catch(e) { + try { const r = await send({ type: 'get_states' }); r.result.forEach(s => { states[s.entity_id] = s; }); } + catch(e2) { console.warn('Could not load initial states:', e2); } + } + try { await send({ type: 'subscribe_events', event_type: 'state_changed' }); } + catch(e) { console.warn('Could not subscribe to events:', e); } + parseCfg(states[CFG_ENTITY]?.state); + render(); } + function onStateChange({ entity_id, new_state }) { states[entity_id] = new_state; if (entity_id === CFG_ENTITY) { parseCfg(new_state?.state); schedRender(); return; }