feat: Enhance WebSocket connection reliability with client-side retry/timeout and faster pings, and disable dashboard caching.

This commit is contained in:
sebseb7
2026-01-18 21:06:58 -05:00
parent 6061567871
commit 75a4d1cbc0
2 changed files with 46 additions and 4 deletions

View File

@@ -198,7 +198,7 @@ const interval = setInterval(() => {
ws.isAlive = false; ws.isAlive = false;
ws.ping(); ws.ping();
}); });
}, 30000); }, 10000);
wss.on('close', () => { wss.on('close', () => {
clearInterval(interval); clearInterval(interval);

View File

@@ -515,23 +515,60 @@ const dashboardHTML = `<!DOCTYPE html>
<script> <script>
let devices = {}; let devices = {};
let ws; let ws;
let retryCount = 0;
let connectionTimeout;
function connectWebSocket() { function connectWebSocket() {
ws = new WebSocket('ws://' + window.location.host); retryCount++;
console.log('WebSocket: Connecting... (attempt ' + retryCount + ')');
document.getElementById('connection-status').textContent = 'Connecting... (attempt ' + retryCount + ')';
// Clear any existing connection
if (ws) {
ws.onclose = null;
ws.onerror = null;
ws.onopen = null;
try { ws.close(); } catch(e) {}
}
try {
ws = new WebSocket('ws://' + window.location.host);
} catch (err) {
console.error('WebSocket: Failed to create', err);
setTimeout(connectWebSocket, 2000);
return;
}
// Connection timeout - abort if no response in 3 seconds
connectionTimeout = setTimeout(() => {
console.log('WebSocket: Connection timeout, retrying...');
if (ws.readyState === WebSocket.CONNECTING) {
ws.close();
}
}, 3000);
ws.onopen = () => { ws.onopen = () => {
clearTimeout(connectionTimeout);
console.log('WebSocket: Connected');
retryCount = 0;
document.getElementById('ws-dot').classList.add('connected'); document.getElementById('ws-dot').classList.add('connected');
document.getElementById('connection-status').textContent = 'Connected'; document.getElementById('connection-status').textContent = 'Connected';
document.getElementById('connection-status').classList.add('connected'); document.getElementById('connection-status').classList.add('connected');
}; };
ws.onclose = () => { ws.onclose = (e) => {
clearTimeout(connectionTimeout);
console.log('WebSocket: Closed', e.code, e.reason);
document.getElementById('ws-dot').classList.remove('connected'); document.getElementById('ws-dot').classList.remove('connected');
document.getElementById('connection-status').textContent = 'Disconnected - Reconnecting...'; document.getElementById('connection-status').textContent = 'Disconnected - Reconnecting...';
document.getElementById('connection-status').classList.remove('connected'); document.getElementById('connection-status').classList.remove('connected');
setTimeout(connectWebSocket, 2000); setTimeout(connectWebSocket, 2000);
}; };
ws.onerror = (e) => {
console.error('WebSocket: Error', e);
};
ws.onmessage = (event) => { ws.onmessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
@@ -841,7 +878,12 @@ const server = http.createServer(async (req, res) => {
// Serve dashboard // Serve dashboard
if (url.pathname === '/' || url.pathname === '/index.html') { if (url.pathname === '/' || url.pathname === '/index.html') {
res.writeHead(200, { 'Content-Type': 'text/html' }); res.writeHead(200, {
'Content-Type': 'text/html',
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
});
res.end(dashboardHTML); res.end(dashboardHTML);
return; return;
} }