Der Socket.IO-Server lief als zweiter Server auf Port 3001 und brauchte
deswegen cors: { origin: "*" }; die Clients bauten ihre Verbindungs-URL aus
window.location.hostname und dem festen Port zusammen.
Er wird jetzt ohne eigenen Port erzeugt und in bin/www per io.attach() an den
bestehenden HTTP-Server gehaengt. Erzeugen und Anhaengen sind getrennt, weil das
Modul beim Laden der Routen ausgewertet wird, also bevor der HTTP-Server
existiert. Die Clients rufen nur noch io() ohne Argument auf und verbinden sich
damit zur Herkunft der Seite zurueck.
Damit entfallen der zweite Port, die CORS-Ausnahme und eine moegliche zweite
Firewall-Regel auf dem Pi. Verifiziert: Port 3001 lauscht nicht mehr, alle
Events (score, timerDurationLeft, timerEnded, scoreSideswitch, refresh) kommen
ueber Port 3000 an, Reconnect funktioniert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>