Skip to content

Commit

Permalink
Improve reconnection handling
Browse files Browse the repository at this point in the history
  • Loading branch information
WarmUpTill committed Oct 1, 2024
1 parent ad34e10 commit cf3483f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/actions/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ export class StatusAction extends SingletonAction<StatusSettings> {
async onWillAppear(ev: WillAppearEvent<StatusSettings>): Promise<void> {
advssConnection.registerStartEventCallback(() => { ev.action.setTitle("Started"); });
advssConnection.registerStopEventCallback(() => { ev.action.setTitle("Stopped"); });
advssConnection.registerDisconnectCallback(() => { ev.action.setTitle("Not\nConnected"); });

await advssConnection.waitForInitialConnectionAttempt();
const isRunning = await advssConnection.isAdvancedSceneSwitcherRunning();
if (!advssConnection.isConnected()) {
ev.action.setTitle("Not\nconnected");
ev.action.setTitle("Not\nConnected");
return;
}
return ev.action.setTitle(`${isRunning ? "Started" : "Stopped"}`);
Expand Down
31 changes: 28 additions & 3 deletions src/advss-connection.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OBSWebSocket, OBSWebSocketError, EventSubscription, OBSResponseTypes } from 'obs-websocket-js';
import streamDeck, { LogLevel } from "@elgato/streamdeck";

declare type StartStopEventCallback = () => void;
declare type EventCallback = () => void;

const logger = streamDeck.logger.createScope("AdvssConnection");

Expand All @@ -28,12 +28,14 @@ export class AdvssConnection {
private initialConnectionAttemptDone: boolean = false;
private startCallbacks: { (): void; }[] = [];
private stopCallbacks: { (): void; }[] = [];
private disconnectCallbacks: { (): void; }[] = [];

private constructor(host: string = "localhost", port: number = 4455, password: string = "password") {
this.port = port;
this.host = host;
this.password = password;
this.obs.on("VendorEvent", (data) => this.parseEvents(data));
this.obs.on("ConnectionClosed", (data) => this.handleConnectionClose(data));
}

private parseEvents(data: any) {
Expand All @@ -47,6 +49,13 @@ export class AdvssConnection {
}
}

private async handleConnectionClose(error: OBSWebSocketError) {
logger.info(`OBS connection closed (${error.code}): ${error.message}`);
this.connected = false;
this.disconnectCallbacks.forEach((callback) => { callback(); });
this.tryDelayedReconnect(5000);
}

private handleStartEvent() {
logger.debug("Start event received");
this.startCallbacks.forEach((callback) => { callback(); });
Expand All @@ -57,14 +66,18 @@ export class AdvssConnection {
this.stopCallbacks.forEach((callback) => { callback(); });
}

public registerStartEventCallback(callback: StartStopEventCallback) {
public registerStartEventCallback(callback: EventCallback) {
this.startCallbacks.push(callback);
}

public registerStopEventCallback(callback: StartStopEventCallback) {
public registerStopEventCallback(callback: EventCallback) {
this.stopCallbacks.push(callback);
}

public registerDisconnectCallback(callback: EventCallback) {
this.disconnectCallbacks.push(callback);
}

public isConnected(): boolean {
return this.connected;
}
Expand Down Expand Up @@ -178,6 +191,18 @@ export class AdvssConnection {
this.sendVendorRequest({ vendorName, requestType, requestData });
}

private async tryDelayedReconnect(delayMs: number) {
logger.debug(`Attempting reconnection in ${delayMs} ms`);
await new Promise(r => setTimeout(r, delayMs));

if (this.connected) {
// Already connected - skip reconnect attempt
return;
}

this.reconnect();
}

public async reconnect(): Promise<void> {
logger.info(`OBS websocket reconnecting`);
this.connected = false;
Expand Down

0 comments on commit cf3483f

Please sign in to comment.