diff --git a/templates/index_v2.html b/templates/index_v2.html
index a1dd648b..a188c838 100644
--- a/templates/index_v2.html
+++ b/templates/index_v2.html
@@ -1779,11 +1779,19 @@
// Socket.IO connection
function initializeSocket() {
- socket = io({ transports: ['websocket', 'polling'] });
+ socket = io({
+ path: '/socket.io',
+ transports: ['websocket', 'polling'],
+ reconnection: true,
+ reconnectionAttempts: Infinity,
+ reconnectionDelay: 1000,
+ reconnectionDelayMax: 10000
+ });
socket.on('connect', function() {
updateConnectionStatus(true);
showNotification('Connected to LED Matrix', 'success');
+ stopPreviewPolling();
});
socket.on('disconnect', function() {
@@ -1800,6 +1808,12 @@
}, delay);
};
retry();
+ startPreviewPolling();
+ });
+
+ socket.on('connect_error', function(_err){
+ updateConnectionStatus(false);
+ startPreviewPolling();
});
socket.on('display_update', function(data) {
@@ -1807,6 +1821,24 @@
});
}
+ // Fallback polling when websocket is disconnected
+ let __previewPollTimer = null;
+ function startPreviewPolling(){
+ if (__previewPollTimer) return;
+ __previewPollTimer = setInterval(fetchCurrentDisplayOnce, 1000);
+ }
+ function stopPreviewPolling(){
+ if (__previewPollTimer) clearInterval(__previewPollTimer);
+ __previewPollTimer = null;
+ }
+ async function fetchCurrentDisplayOnce(){
+ try {
+ const res = await fetch('/api/display/current');
+ const data = await res.json();
+ if (data && data.image) updateDisplayPreview(data);
+ } catch (_) {}
+ }
+
// Draw pixel grid lines on top of scaled image
function drawGrid(canvas, logicalWidth, logicalHeight, scale) {
const show = document.getElementById('toggleGrid')?.checked;
diff --git a/web_interface_v2.py b/web_interface_v2.py
index 66862703..2e42de05 100644
--- a/web_interface_v2.py
+++ b/web_interface_v2.py
@@ -851,9 +851,23 @@ def get_current_display():
def handle_connect():
"""Handle client connection."""
emit('connected', {'status': 'Connected to LED Matrix Interface'})
- # Send current display state
- if current_display_data:
- emit('display_update', current_display_data)
+ # Send current display state immediately after connect
+ try:
+ if display_manager and hasattr(display_manager, 'image'):
+ img_buffer = io.BytesIO()
+ display_manager.image.save(img_buffer, format='PNG')
+ img_str = base64.b64encode(img_buffer.getvalue()).decode()
+ payload = {
+ 'image': img_str,
+ 'width': display_manager.width,
+ 'height': display_manager.height,
+ 'timestamp': time.time()
+ }
+ emit('display_update', payload)
+ elif current_display_data:
+ emit('display_update', current_display_data)
+ except Exception as e:
+ logger.error(f"Error sending initial display_update on connect: {e}")
@socketio.on('disconnect')
def handle_disconnect():
@@ -872,7 +886,7 @@ if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
- # Start the display monitor
+ # Start the display monitor (runs even if display is not started yet for web preview)
display_monitor.start()
# Run the app