This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user