web sockety things
Build Images and Deploy / Update-PROD-Stack (push) Successful in 19s

This commit is contained in:
2026-03-30 23:21:23 -04:00
parent 0a4ff9bf76
commit cd0ca8cf7c
+47 -2
View File
@@ -606,23 +606,54 @@ async function api(method, path, body) {
// ── WebSocket ────────────────────────────────────────────────────────────── // ── WebSocket ──────────────────────────────────────────────────────────────
function connectWS() { function connectWS() {
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:'; const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
ws = new WebSocket(`${proto}//${location.host}`); const wsUrl = `${proto}//${location.host}`;
console.log(`[DWM] Connecting WebSocket to: ${wsUrl}`);
try {
ws = new WebSocket(wsUrl);
} catch (err) {
console.error('[DWM] WebSocket creation failed:', err);
return;
}
ws.onopen = () => { ws.onopen = () => {
console.log('[DWM] WebSocket connected');
document.querySelectorAll('.ws-dot').forEach((d) => d.classList.add('connected')); document.querySelectorAll('.ws-dot').forEach((d) => d.classList.add('connected'));
document.querySelectorAll('[id^="ws-label"]').forEach((l) => l.textContent = 'Connected'); document.querySelectorAll('[id^="ws-label"]').forEach((l) => l.textContent = 'Connected');
}; };
ws.onclose = () => { ws.onclose = () => {
console.log('[DWM] WebSocket disconnected, reconnecting...');
document.querySelectorAll('.ws-dot').forEach((d) => d.classList.remove('connected')); document.querySelectorAll('.ws-dot').forEach((d) => d.classList.remove('connected'));
document.querySelectorAll('[id^="ws-label"]').forEach((l) => l.textContent = 'Reconnecting…'); document.querySelectorAll('[id^="ws-label"]').forEach((l) => l.textContent = 'Reconnecting…');
setTimeout(connectWS, 4000); setTimeout(connectWS, 4000);
}; };
ws.onerror = (error) => {
console.error('[DWM] WebSocket error:', error);
document.querySelectorAll('.ws-dot').forEach((d) => d.classList.remove('connected'));
document.querySelectorAll('[id^="ws-label"]').forEach((l) => l.textContent = 'Connection Error');
// Show user-friendly error message
if (error.type === 'error' && error.message.includes('SSL')) {
toast('WebSocket SSL Error: Try accessing via domain name or check certificate', 'error');
} else if (error.message) {
toast(`WebSocket Error: ${error.message}`, 'error');
} else {
toast('WebSocket connection failed - try refreshing the page', 'error');
}
};
ws.onmessage = (e) => { ws.onmessage = (e) => {
try { try {
const { type, data } = JSON.parse(e.data); const { type, data } = JSON.parse(e.data);
if (type === 'scheduler-fired') appendLog(data); if (type === 'scheduler-fired') appendLog(data);
if (type === 'scheduler-status') applySchedStatus(data); if (type === 'scheduler-status') applySchedStatus(data);
if (type === 'scheduler-health') appendLog({ success: data.online, msg: `[health] ${data.msg}` }); if (type === 'scheduler-health') appendLog({ success: data.online, msg: `[health] ${data.msg}` });
} catch {} } catch (err) {
console.error('[DWM] WebSocket message parse error:', err);
}
}; };
} }
@@ -670,6 +701,14 @@ function renderDevices() {
el.innerHTML = `<div class="empty"><div class="icon">📡</div><p>No devices found.<br>Tap <strong>Scan</strong> to search.</p></div>`; el.innerHTML = `<div class="empty"><div class="icon">📡</div><p>No devices found.<br>Tap <strong>Scan</strong> to search.</p></div>`;
return; return;
} }
// Check if there are WebSocket connection issues
const wsConnected = ws && ws.readyState === WebSocket.OPEN;
if (!wsConnected) {
el.innerHTML = `<div class="empty"><div class="icon">⚠️</div><p>WebSocket connection issue detected.<br>Device states may not be accurate.<br>Try refreshing the page.</p></div>`;
return;
}
el.innerHTML = devices.map((d, i) => { el.innerHTML = devices.map((d, i) => {
const name = d.friendlyName || d.name || d.host; const name = d.friendlyName || d.name || d.host;
const isDimmer = d.isDimmer || false; const isDimmer = d.isDimmer || false;
@@ -709,6 +748,12 @@ function renderDevices() {
// fetch current state for each device // fetch current state for each device
devices.forEach((d, i) => { devices.forEach((d, i) => {
// Skip fetching state if WebSocket is not connected
if (!ws || ws.readyState !== WebSocket.OPEN) {
console.log(`[DWM] Skipping device state fetch due to WebSocket connection issues`);
return;
}
// For dimmer devices, fetch both brightness and state // For dimmer devices, fetch both brightness and state
if (d.isDimmer) { if (d.isDimmer) {
// Fetch brightness first // Fetch brightness first