diff --git a/android/src/services/rvs.ts b/android/src/services/rvs.ts index dcb6d39..8889585 100644 --- a/android/src/services/rvs.ts +++ b/android/src/services/rvs.ts @@ -104,11 +104,7 @@ class RVSConnection { // Verbindungen + doppelte Events. if (this.ws) { this.log('info', 'Bestehende WS-Verbindung wird geschlossen vor Neu-Connect'); - try { - this.ws.onclose = null; // verhindert dass scheduleReconnect doppelt feuert - this.ws.onerror = null; - this.ws.close(); - } catch (_) {} + this.detachSocket(this.ws); this.ws = null; } @@ -215,7 +211,12 @@ class RVSConnection { this.startHeartbeat(); }; + const socket = this.ws; // genau DIESE Verbindung (nicht 'this.ws' spaeter) this.ws.onmessage = (event: WebSocketMessageEvent) => { + // Nur die AKTUELLE Verbindung darf Nachrichten einspeisen. Sonst + // koennte eine alte, laengst aufgegebene Verbindung weiter Daten + // liefern und vortaeuschen, es sei alles in Ordnung. + if (socket !== this.ws) return; try { const message: RVSMessage = JSON.parse(event.data as string); this.notifyMessageListeners(message); @@ -258,8 +259,7 @@ class RVSConnection { this.log('warn', 'TLS fehlgeschlagen — Fallback auf ws:// (ohne TLS)'); this.clearTimers(); if (this.ws) { - this.ws.onclose = null; // onclose-Handler entfernen um Doppel-Reconnect zu verhindern - try { this.ws.close(); } catch (_) {} + this.detachSocket(this.ws); // inkl. onmessage — sonst bleibt ein Zombie, der weiter empfaengt } this.ws = null; this.shouldReconnect = true; @@ -302,6 +302,25 @@ class RVSConnection { }, HEARTBEAT_INTERVAL_MS); } + /** + * Klemmt eine Verbindung VOLLSTAENDIG ab, bevor sie verworfen wird. + * + * Wichtig: frueher wurden nur onclose/onerror entfernt — onmessage blieb + * haengen. Eine aufgegebene (Zombie-)Verbindung lieferte dadurch weiter + * Nachrichten an die App, waehrend gesendet wurde ueber die neue/tote. + * Symptom: die App zeigt "getrennt", ARIAs Sprachausgabe kommt aber trotzdem + * an — und nichts, was man schreibt oder spricht, erreicht den Server. + */ + private detachSocket(ws: WebSocket): void { + try { + ws.onopen = null; + ws.onmessage = null; // <- das fehlte + ws.onclose = null; // verhindert doppelten Reconnect + ws.onerror = null; + ws.close(); + } catch (_) {} + } + private clearTimers(): void { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer);