Server-side events (SSE) namesto pollinga #14
This commit is contained in:
@@ -28,8 +28,10 @@ than being generated inside Python code.
|
||||
import threading
|
||||
import os
|
||||
import json
|
||||
import queue
|
||||
import time
|
||||
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
from flask import Flask, render_template, request, jsonify, Response
|
||||
|
||||
# create Flask app with proper folders relative to this file
|
||||
app = Flask(__name__, static_folder="static", template_folder="templates")
|
||||
@@ -37,6 +39,17 @@ app = Flask(__name__, static_folder="static", template_folder="templates")
|
||||
# Globalna referenca na SongProjector aplikaciju
|
||||
_projector_app = None
|
||||
|
||||
# List of queues for SSE clients
|
||||
_sse_clients = []
|
||||
_sse_lock = threading.Lock()
|
||||
|
||||
|
||||
def notify_clients():
|
||||
"""Notify all connected SSE clients to refresh content"""
|
||||
with _sse_lock:
|
||||
for q in _sse_clients:
|
||||
q.put("refresh content")
|
||||
|
||||
|
||||
def set_projector_app(projector_app):
|
||||
"""Postavi referenco na SongProjector aplikacijo"""
|
||||
@@ -97,6 +110,26 @@ def get_state():
|
||||
})
|
||||
|
||||
|
||||
@app.route('/api/events')
|
||||
def sse_events():
|
||||
"""SSE endpoint for real-time updates"""
|
||||
def event_stream():
|
||||
q = queue.Queue()
|
||||
with _sse_lock:
|
||||
_sse_clients.append(q)
|
||||
try:
|
||||
# Send initial refresh command on connection
|
||||
yield "data: refresh content\n\n"
|
||||
while True:
|
||||
msg = q.get()
|
||||
yield f"data: {msg}\n\n"
|
||||
finally:
|
||||
with _sse_lock:
|
||||
_sse_clients.remove(q)
|
||||
|
||||
return Response(event_stream(), mimetype="text/event-stream")
|
||||
|
||||
|
||||
@app.route('/api/load_song', methods=['POST'])
|
||||
def load_song():
|
||||
"""Naloži pesem po številki"""
|
||||
@@ -111,6 +144,7 @@ def load_song():
|
||||
_projector_app.load_song()
|
||||
if hasattr(_projector_app, 'show_page'):
|
||||
_projector_app.show_page()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -120,6 +154,7 @@ def next_page():
|
||||
"""Naslednja stran"""
|
||||
if _projector_app is not None:
|
||||
_projector_app.next_page()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -129,6 +164,7 @@ def prev_page():
|
||||
"""Prejšnja stran"""
|
||||
if _projector_app is not None:
|
||||
_projector_app.prev_page()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -138,6 +174,7 @@ def clear_screen():
|
||||
"""Zatemniti ekran"""
|
||||
if _projector_app is not None:
|
||||
_projector_app.clear_screen()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -148,6 +185,7 @@ def toggle_caps():
|
||||
if _projector_app is not None:
|
||||
_projector_app.all_caps_mode = not _projector_app.all_caps_mode
|
||||
_projector_app.show_page()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -157,6 +195,7 @@ def toggle_split():
|
||||
"""Preklop med načinom preloma po kiticah in prostim prelomom"""
|
||||
if _projector_app is not None:
|
||||
_projector_app.toggle_split_mode()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
@@ -283,6 +322,7 @@ def update_song():
|
||||
if str(_projector_app.song_number_last) == str(song_id):
|
||||
_projector_app.song_number = str(song_id)
|
||||
_projector_app.load_song()
|
||||
notify_clients()
|
||||
|
||||
return jsonify({'status': 'ok'})
|
||||
except Exception as e:
|
||||
|
||||
@@ -648,9 +648,24 @@ document.addEventListener('keydown', (e) => {
|
||||
updateState(true);
|
||||
requestWakeLock();
|
||||
|
||||
// osveževanje za sinhronizacijo med več napravami
|
||||
setInterval(() => {
|
||||
updateState(false);
|
||||
}, 1000);
|
||||
// SSE osveževanje za sinhronizacijo med več napravami
|
||||
function setupSSE() {
|
||||
const evtSource = new EventSource("/api/events");
|
||||
|
||||
evtSource.onmessage = function(event) {
|
||||
console.log("SSE dogodek:", event.data);
|
||||
if (event.data === "refresh content") {
|
||||
updateState(false);
|
||||
}
|
||||
};
|
||||
|
||||
evtSource.onerror = function(err) {
|
||||
console.error("SSE napaka, ponovni poskus čez 5s...", err);
|
||||
evtSource.close();
|
||||
setTimeout(setupSSE, 5000);
|
||||
};
|
||||
}
|
||||
|
||||
setupSSE();
|
||||
|
||||
console.log('JavaScript inicializacija zaključena');
|
||||
Reference in New Issue
Block a user