Frontend: Reconnect-Sync, Dropdowns ohne String-Interpolation, Fehlerpfad
Alle vier Frontends horchten auf ein Event 'connected', das nie gesendet wurde; der Server verschickte stattdessen ein Event mit dem Namen "Hello user from server" und leerem Payload. Beides ist entfernt. An seine Stelle tritt das Socket.IO-eigene 'connect', das auch nach einem Reconnect feuert: Adminpanel und Monitor holen sich dort den aktuellen Stand. Da der Pi das WLAN selbst aufspannt, sind kurze Abbrueche im Betrieb normal — bisher blieb die Anzeige danach auf einem veralteten Stand stehen, bis das naechste Ereignis eintraf. Die Teamnamen-Dropdowns bauten ihre Eintraege als HTML-String zusammen und interpolierten den Namen in einen onclick-Aufruf. Ein Name mit Apostroph, etwa "SG D'Horn", zerlegte den Handler und machte den Eintrag unbrauchbar. Die Eintraege entstehen jetzt ueber createTeamDropdownItem() mit textContent und addEventListener, der Name kommt per Closure statt als String. Die Schleifenvariable ist zudem korrekt deklariert, vorher war sie global. fetchJson() kapselt Anfragen und liefert null, wenn der Server nicht erreichbar ist oder mit einem Fehler antwortet, statt still in der Konsole zu scheitern. timerStart und timerPause behalten ihre eigene Auswertung des 406-Status. Das Verbindungs-Handling ist von routes/index.js nach controllers/socketio.js gewandert, wo der Socket.IO-Server erzeugt wird, und protokolliert jetzt auch Verbindungsabbrueche. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6f4c63aa6e
commit
cd4877bdd2
6 changed files with 132 additions and 92 deletions
|
|
@ -9,4 +9,15 @@ const io = new Server(3001, {
|
||||||
cors: { origin: "*" }
|
cors: { origin: "*" }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Verbindungs-Handling: der Client meldet sich beim Verbinden selbst mit dem
|
||||||
|
// Socket.IO-eigenen 'connect'-Event und holt sich den aktuellen Stand ueber die
|
||||||
|
// REST-Endpunkte. Serverseitig wird die Verbindung nur protokolliert.
|
||||||
|
io.on('connection', (socket) => {
|
||||||
|
console.log("A user connected");
|
||||||
|
|
||||||
|
socket.on('disconnect', (reason) => {
|
||||||
|
console.log("A user disconnected: ", reason);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = io
|
module.exports = io
|
||||||
|
|
@ -5,8 +5,12 @@ const socket = io(wss); // Conne
|
||||||
// Websockets event handler
|
// Websockets event handler
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
socket.on('connected', (message) => { // Once client is connected to websocket
|
// 'connect' feuert bei jeder Verbindung, auch nach einem Reconnect. Da der Pi das
|
||||||
console.log("Connected");
|
// WLAN selbst aufspannt, sind kurze Abbrueche normal: danach werden die Werte neu
|
||||||
|
// geholt, damit das Panel nicht auf einem veralteten Stand stehen bleibt.
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log("Verbunden");
|
||||||
|
initialUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('timerDurationLeft', (message) => {
|
socket.on('timerDurationLeft', (message) => {
|
||||||
|
|
@ -28,6 +32,22 @@ socket.on('score', (message) => {
|
||||||
// General functions
|
// General functions
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
|
// Holt JSON von einem Endpunkt. Liefert null statt zu werfen, wenn der Server nicht
|
||||||
|
// erreichbar ist oder mit einem Fehler antwortet — sonst bricht der Aufrufer still ab.
|
||||||
|
async function fetchJson(url, options) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, options);
|
||||||
|
if(!response.ok) {
|
||||||
|
console.error("Anfrage fehlgeschlagen:", url, response.status);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Server nicht erreichbar:", url, err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initial update gets called whenever page has been loaded
|
// Initial update gets called whenever page has been loaded
|
||||||
async function initialUpdate() {
|
async function initialUpdate() {
|
||||||
etcGetValues(); // Request new values for etc stuff
|
etcGetValues(); // Request new values for etc stuff
|
||||||
|
|
@ -104,6 +124,19 @@ function updateScoreFrontend(values) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erzeugt einen Dropdown-Eintrag, der den Teamnamen in das angegebene Feld uebernimmt.
|
||||||
|
// Der Name wird als Text gesetzt und per Closure an den Handler gegeben, statt ihn in
|
||||||
|
// einen onclick-String zu schreiben: Namen mit Apostroph zerlegten sonst den Handler.
|
||||||
|
function createTeamDropdownItem(field, team) {
|
||||||
|
const li = document.createElement("li");
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.className = "dropdown-item";
|
||||||
|
a.textContent = team;
|
||||||
|
a.addEventListener("click", () => scoreInsertChosenName(field, team));
|
||||||
|
li.appendChild(a);
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
// Update DOM for all db contents with the passed values
|
// Update DOM for all db contents with the passed values
|
||||||
function updateDbFrontend(values) {
|
function updateDbFrontend(values) {
|
||||||
console.log(values);
|
console.log(values);
|
||||||
|
|
@ -122,27 +155,17 @@ function updateDbFrontend(values) {
|
||||||
let selectDelete = document.getElementById("dbTeamToDelete"); // Select for team deletion from db
|
let selectDelete = document.getElementById("dbTeamToDelete"); // Select for team deletion from db
|
||||||
selectDelete.innerHTML = "" // Clears all existing options from select
|
selectDelete.innerHTML = "" // Clears all existing options from select
|
||||||
|
|
||||||
// <li><a class="dropdown-item" onclick="scoreInsertChosenName">Action</a></li>
|
for(const team of values.teams) {
|
||||||
|
|
||||||
for(team of values.teams) {
|
|
||||||
// Create custom Dropdowns with different function arguments for team configuration
|
// Create custom Dropdowns with different function arguments for team configuration
|
||||||
var li = document.createElement("li");
|
teamAnameDropdown.appendChild(createTeamDropdownItem("teamAname", team));
|
||||||
li.innerHTML = `<a class="dropdown-item" onclick="scoreInsertChosenName('teamAname','` + team +`')"> `+ team +`</a>`;
|
teamAname2Dropdown.appendChild(createTeamDropdownItem("teamAname2", team));
|
||||||
teamAnameDropdown.appendChild(li);
|
teamBnameDropdown.appendChild(createTeamDropdownItem("teamBname", team));
|
||||||
var li = document.createElement("li");
|
teamBname2Dropdown.appendChild(createTeamDropdownItem("teamBname2", team));
|
||||||
li.innerHTML = `<a class="dropdown-item" onclick="scoreInsertChosenName('teamAname2','` + team +`')"> `+ team +`</a>`;
|
|
||||||
teamAname2Dropdown.appendChild(li);
|
|
||||||
var li = document.createElement("li");
|
|
||||||
li.innerHTML = `<a class="dropdown-item" onclick="scoreInsertChosenName('teamBname','` + team +`')"> `+ team +`</a>`;
|
|
||||||
teamBnameDropdown.appendChild(li);
|
|
||||||
var li = document.createElement("li");
|
|
||||||
li.innerHTML = `<a class="dropdown-item" onclick="scoreInsertChosenName('teamBname2','` + team +`')"> `+ team +`</a>`;
|
|
||||||
teamBname2Dropdown.appendChild(li);
|
|
||||||
|
|
||||||
// Create select options for deletion in debugwindow
|
// Create select options for deletion in debugwindow
|
||||||
let opt = document.createElement("option");
|
let opt = document.createElement("option");
|
||||||
opt.value = team;
|
opt.value = team;
|
||||||
opt.innerHTML = team;
|
opt.textContent = team;
|
||||||
selectDelete.appendChild(opt);
|
selectDelete.appendChild(opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,16 +207,14 @@ async function killBrowser() {
|
||||||
|
|
||||||
// Request important values for etc stuff
|
// Request important values for etc stuff
|
||||||
async function etcGetValues() {
|
async function etcGetValues() {
|
||||||
const response = await fetch("/admin/etcGetValues"); // Call API Endpoint /admin/etcGetValues
|
const data = await fetchJson("/admin/etcGetValues"); // Call API Endpoint /admin/etcGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateEtcFrontend(data); // Update admin frontend
|
||||||
updateEtcFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle index page to also show scoreboard
|
// Toggle index page to also show scoreboard
|
||||||
async function etcToggleSplashscreen() {
|
async function etcToggleSplashscreen() {
|
||||||
const response = await fetch("/admin/etcToggleSplashscreen");// Call API Endpoint /admin/etcToggleSplashscreen
|
const data = await fetchJson("/admin/etcToggleSplashscreen");// Call API Endpoint /admin/etcToggleSplashscreen
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateEtcFrontend(data); // Update admin frontend
|
||||||
updateEtcFrontend(data); // Update admin frontend
|
|
||||||
refreshMonitor(); // Refresh main monitor to display new frontend
|
refreshMonitor(); // Refresh main monitor to display new frontend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,9 +224,8 @@ async function etcToggleSplashscreen() {
|
||||||
|
|
||||||
// Request important timer values
|
// Request important timer values
|
||||||
async function timerGetValues() {
|
async function timerGetValues() {
|
||||||
const response = await fetch("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
const data = await fetchJson("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateTimerFrontend(data); // Update admin frontend
|
||||||
updateTimerFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request to start the timer
|
// Request to start the timer
|
||||||
|
|
@ -235,24 +255,22 @@ async function timerPause() {
|
||||||
// Request to reset the timer with the specified time
|
// Request to reset the timer with the specified time
|
||||||
async function timerReset() {
|
async function timerReset() {
|
||||||
let newDuration = document.getElementById("timerSelectDuration").value;
|
let newDuration = document.getElementById("timerSelectDuration").value;
|
||||||
const response = await fetch("/admin/timerReset", { // Call API Endpoint /admin/timerStart with selected new duration in seconds
|
const data = await fetchJson("/admin/timerReset", { // Call API Endpoint /admin/timerStart with selected new duration in seconds
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({duration: newDuration})
|
body: JSON.stringify({duration: newDuration})
|
||||||
});
|
});
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateTimerFrontend(data); // Update admin frontend
|
||||||
updateTimerFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request to increase or decrease the timer depending on passed value in seconds
|
// Request to increase or decrease the timer depending on passed value in seconds
|
||||||
async function timerIncDec(value) {
|
async function timerIncDec(value) {
|
||||||
const response = await fetch("/admin/timerIncDec", { // Call API Endpoint /admin/timerIncDec with value in seconds to increase or decrease the timer
|
const data = await fetchJson("/admin/timerIncDec", { // Call API Endpoint /admin/timerIncDec with value in seconds to increase or decrease the timer
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({value: value})
|
body: JSON.stringify({value: value})
|
||||||
});
|
});
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateTimerFrontend(data); // Update admin frontend
|
||||||
updateTimerFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
@ -261,49 +279,43 @@ async function timerIncDec(value) {
|
||||||
|
|
||||||
// Request important values for score
|
// Request important values for score
|
||||||
async function scoreGetValues() {
|
async function scoreGetValues() {
|
||||||
const response = await fetch("/admin/scoreGetValues"); // Call API Endpoint /admin/scoreGetValues
|
const data = await fetchJson("/admin/scoreGetValues"); // Call API Endpoint /admin/scoreGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle index page to also show scoreboard
|
// Toggle index page to also show scoreboard
|
||||||
async function scoreToggle() {
|
async function scoreToggle() {
|
||||||
const response = await fetch("/admin/scoreToggle"); // Call API Endpoint /admin/scoreToggle
|
const data = await fetchJson("/admin/scoreToggle"); // Call API Endpoint /admin/scoreToggle
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
refreshMonitor(); // Refresh main monitor to display new frontend
|
refreshMonitor(); // Refresh main monitor to display new frontend
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alter the score of passed team in the specified direction
|
// Alter the score of passed team in the specified direction
|
||||||
async function scoreAlterScore(team, dir) {
|
async function scoreAlterScore(team, dir) {
|
||||||
const response = await fetch("/admin/scoreAlterScore", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
const data = await fetchJson("/admin/scoreAlterScore", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({team: team, dir: dir})
|
body: JSON.stringify({team: team, dir: dir})
|
||||||
});
|
});
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch sides
|
// Switch sides
|
||||||
async function scoreToggleSideswitch() {
|
async function scoreToggleSideswitch() {
|
||||||
const response = await fetch("/admin/scoreToggleSideswitch");// Call API Endpoint /admin/scoreSwitch
|
const data = await fetchJson("/admin/scoreToggleSideswitch");// Call API Endpoint /admin/scoreSwitch
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch sides to mirror admin panel when sitting behind main monitor
|
// Switch sides to mirror admin panel when sitting behind main monitor
|
||||||
async function scoreToggleReferenceMirrored() {
|
async function scoreToggleReferenceMirrored() {
|
||||||
const response = await fetch("/admin/scoreToggleReferenceMirrored");// Call API Endpoint /admin/scoreSwitch
|
const data = await fetchJson("/admin/scoreToggleReferenceMirrored");// Call API Endpoint /admin/scoreSwitch
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear score
|
// Clear score
|
||||||
async function scoreClearScore() {
|
async function scoreClearScore() {
|
||||||
const response = await fetch("/admin/scoreClearScore"); // Call API Endpoint /admin/scoreClearScore
|
const data = await fetchJson("/admin/scoreClearScore"); // Call API Endpoint /admin/scoreClearScore
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure Teams
|
// Configure Teams
|
||||||
|
|
@ -320,13 +332,12 @@ async function scoreConfigTeams() {
|
||||||
}
|
}
|
||||||
console.log(teamA, teamB)
|
console.log(teamA, teamB)
|
||||||
|
|
||||||
const response = await fetch("/admin/scoreConfigTeams", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
const data = await fetchJson("/admin/scoreConfigTeams", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({teamA: teamA, teamB: teamB})
|
body: JSON.stringify({teamA: teamA, teamB: teamB})
|
||||||
});
|
});
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateScoreFrontend(data); // Update admin frontend
|
||||||
updateScoreFrontend(data); // Update admin frontend
|
|
||||||
refreshMonitor();
|
refreshMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,31 +347,28 @@ async function scoreConfigTeams() {
|
||||||
|
|
||||||
// Request important values for db contents
|
// Request important values for db contents
|
||||||
async function dbGetValues() {
|
async function dbGetValues() {
|
||||||
const response = await fetch("/admin/dbGetValues"); // Call API Endpoint /admin/dbGetValues
|
const data = await fetchJson("/admin/dbGetValues"); // Call API Endpoint /admin/dbGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateDbFrontend(data); // Update admin frontend
|
||||||
updateDbFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add team to DB
|
// Add team to DB
|
||||||
async function dbAddTeam() {
|
async function dbAddTeam() {
|
||||||
const response = await fetch("/admin/dbAddTeam", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
const data = await fetchJson("/admin/dbAddTeam", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({teamName: document.getElementById("dbTeamToAdd").value})
|
body: JSON.stringify({teamName: document.getElementById("dbTeamToAdd").value})
|
||||||
});
|
});
|
||||||
document.getElementById("dbTeamToAdd").value = ""; // Empty the text field after sending
|
document.getElementById("dbTeamToAdd").value = ""; // Empty the text field after sending
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateDbFrontend(data);
|
||||||
updateDbFrontend(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete team from DB
|
// Delete team from DB
|
||||||
async function dbDeleteTeam() {
|
async function dbDeleteTeam() {
|
||||||
let teamName = document.getElementById("dbTeamToDelete").value;
|
let teamName = document.getElementById("dbTeamToDelete").value;
|
||||||
const response = await fetch("/admin/dbDeleteTeam", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
const data = await fetchJson("/admin/dbDeleteTeam", { // Call API Endpoint /admin/scoreAlterScore with the teamname to alter the score in the specified direction
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({teamName: teamName})
|
body: JSON.stringify({teamName: teamName})
|
||||||
});
|
});
|
||||||
const data = await response.json(); // Wait for asyncronous transfer to complete
|
if(data) updateDbFrontend(data);
|
||||||
updateDbFrontend(data);
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,8 +5,12 @@ const socket = io(wss); // Connect to socketio s
|
||||||
// Websockets event handler
|
// Websockets event handler
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
socket.on('connected', (message) => {
|
// 'connect' feuert bei jeder Verbindung, auch nach einem Reconnect. Da der Pi das WLAN
|
||||||
console.log("Connected");
|
// selbst aufspannt, sind kurze Abbrueche normal: danach werden Timer und Spielstand neu
|
||||||
|
// geholt, damit die Anzeige nicht auf einem veralteten Stand haengen bleibt.
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log("Verbunden");
|
||||||
|
initialUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('timerDurationLeft', (message) => {
|
socket.on('timerDurationLeft', (message) => {
|
||||||
|
|
@ -26,6 +30,22 @@ socket.on('refresh', (message) => {
|
||||||
// General functions
|
// General functions
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
|
// Holt JSON von einem Endpunkt. Liefert null statt zu werfen, wenn der Server nicht
|
||||||
|
// erreichbar ist oder mit einem Fehler antwortet.
|
||||||
|
async function fetchJson(url) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
if(!response.ok) {
|
||||||
|
console.error("Anfrage fehlgeschlagen:", url, response.status);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Server nicht erreichbar:", url, err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update DOM timer elements from passed values
|
// Update DOM timer elements from passed values
|
||||||
function updateTimerFrontend(values) {
|
function updateTimerFrontend(values) {
|
||||||
document.getElementById("durationLeft").innerHTML = values.print; // Display durationLeft as prettyfied string
|
document.getElementById("durationLeft").innerHTML = values.print; // Display durationLeft as prettyfied string
|
||||||
|
|
@ -42,7 +62,6 @@ async function initialUpdate() {
|
||||||
|
|
||||||
// Request important timer values
|
// Request important timer values
|
||||||
async function timerGetValues() {
|
async function timerGetValues() {
|
||||||
const response = await fetch("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
const data = await fetchJson("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateTimerFrontend(data); // Update admin frontend
|
||||||
updateTimerFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,8 +5,12 @@ const socket = io(wss); // Connect to socketio s
|
||||||
// Websockets event handler
|
// Websockets event handler
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
socket.on('connected', (message) => {
|
// 'connect' feuert bei jeder Verbindung, auch nach einem Reconnect. Da der Pi das WLAN
|
||||||
console.log("Connected");
|
// selbst aufspannt, sind kurze Abbrueche normal: danach werden Timer und Spielstand neu
|
||||||
|
// geholt, damit die Anzeige nicht auf einem veralteten Stand haengen bleibt.
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log("Verbunden");
|
||||||
|
initialUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('timerDurationLeft', (message) => {
|
socket.on('timerDurationLeft', (message) => {
|
||||||
|
|
@ -35,6 +39,22 @@ socket.on('scoreSideswitch', (message) => {
|
||||||
// General functions
|
// General functions
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
|
// Holt JSON von einem Endpunkt. Liefert null statt zu werfen, wenn der Server nicht
|
||||||
|
// erreichbar ist oder mit einem Fehler antwortet.
|
||||||
|
async function fetchJson(url) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
if(!response.ok) {
|
||||||
|
console.error("Anfrage fehlgeschlagen:", url, response.status);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Server nicht erreichbar:", url, err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update DOM timer elements from passed values
|
// Update DOM timer elements from passed values
|
||||||
function updateTimerFrontend(values) {
|
function updateTimerFrontend(values) {
|
||||||
document.getElementById("durationLeft").innerHTML = values.print; // Display durationLeft as prettyfied string
|
document.getElementById("durationLeft").innerHTML = values.print; // Display durationLeft as prettyfied string
|
||||||
|
|
@ -87,9 +107,8 @@ async function initialUpdate() {
|
||||||
|
|
||||||
// Request important timer values
|
// Request important timer values
|
||||||
async function timerGetValues() {
|
async function timerGetValues() {
|
||||||
const response = await fetch("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
const data = await fetchJson("/admin/timerGetValues"); // Call API Endpoint /admin/timerGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete
|
if(data) updateTimerFrontend(data); // Update admin frontend
|
||||||
updateTimerFrontend(data); // Update admin frontend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
@ -98,8 +117,7 @@ async function timerGetValues() {
|
||||||
|
|
||||||
// Request important values for score
|
// Request important values for score
|
||||||
async function scoreGetValues() {
|
async function scoreGetValues() {
|
||||||
const response = await fetch("/admin/scoreGetValues"); // Call API Endpoint /admin/scoreGetValues
|
const data = await fetchJson("/admin/scoreGetValues"); // Call API Endpoint /admin/scoreGetValues
|
||||||
const data = await response.json(); // Wait for asynchronous transfer to complete and parse json (which got received by backend)
|
|
||||||
console.log(data); // Print received data
|
console.log(data); // Print received data
|
||||||
updateScoreFrontend(data); // Update admin frontend with received values for scoreboard
|
if(data) updateScoreFrontend(data); // Update admin frontend with received values for scoreboard
|
||||||
}
|
}
|
||||||
|
|
@ -5,10 +5,6 @@ const socket = io(wss); // Connect to socketio s
|
||||||
// Websockets event handler
|
// Websockets event handler
|
||||||
// ######################################################################################################################################################
|
// ######################################################################################################################################################
|
||||||
|
|
||||||
socket.on('connected', (message) => {
|
|
||||||
console.log("Connected");
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('refresh', (message) => {
|
socket.on('refresh', (message) => {
|
||||||
document.location.reload() // Reload page on received 'refresh' messagen
|
document.location.reload() // Reload page on received 'refresh' messagen
|
||||||
});
|
});
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var router = express.Router();
|
var router = express.Router();
|
||||||
let io = require('../controllers/socketio');
|
|
||||||
|
|
||||||
const score = require('../controllers/score');
|
const score = require('../controllers/score');
|
||||||
const etc = require('../controllers/etc');
|
const etc = require('../controllers/etc');
|
||||||
|
|
@ -18,15 +17,4 @@ router.get('/', function(req, res, next) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Websocket-Verbindungshandler: wird ausgelöst, sobald ein Client (Monitor) sich verbindet
|
|
||||||
io.on('connection', (socket) => {
|
|
||||||
console.log("A user connected");
|
|
||||||
socket.emit("Hello user from server"); // Begrüßungsnachricht an den neuen Client
|
|
||||||
|
|
||||||
// Eingehende Nachrichten vom Client loggen (aktuell nur für Debugging)
|
|
||||||
socket.on('message', (message) => {
|
|
||||||
console.log(message)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue