elgatosf / streamdeck-plugin-template

A starting place for a new JavaScript Stream Deck plugin.
MIT License
180 stars 69 forks source link

WebSocket stops working after PC is returning from sleep: WebSocket is already in CLOSING or CLOSED state #1

Open CrazyCoder opened 1 year ago

CrazyCoder commented 1 year ago

I noticed extensions based on this template may stop working when the PC is waking from sleep (Windows 10).

api.js:160 WebSocket is already in CLOSING or CLOSED state.
send    @   api.js:160
setTitle    @   stream-deck.js:94
sendRequest @   app.js:63

API needs to handle this case and create a new socket automatically.

CrazyCoder commented 1 year ago

Proposed patch for api.js which fixes the issue for me:

@@ -27,7 +27,10 @@
        this.actionInfo = actionString ? JSON.parse(actionString) : null;
        this.appInfo = JSON.parse(appInfoString);
        this.language = this.appInfo?.application?.language ?? null;
+       this.initWebSocket();
+   }

+   initWebSocket() {
        if (this.websocket) {
            this.websocket.close();
            this.websocket = null;
@@ -66,7 +69,7 @@
        this.websocket.onmessage = (evt) => {
            const data = evt?.data ? JSON.parse(evt.data) : null;

-           const { action, event } = data;
+           const {action, event} = data;
            const message = action ? `${action}.${event}` : event;
            if (message && message !== '') this.emit(message, data);
        };
@@ -157,6 +160,10 @@
     * @param {object} [payload]
     */
    send(context, event, payload = {}) {
+       if (!this.websocket || this.websocket.readyState !== this.websocket.OPEN) {
+           console.warn('WebSocket closed, initWebSocket.');
+           this.initWebSocket();
+       }
        this.websocket && this.websocket.send(JSON.stringify({ context, event, ...payload }));
    }

I noticed that many other plug-ins are affected by this issue as well. Not sure if it's something that has to be fixed in the SDK itself so that plug-in developers don't have to handle it manually.

Other affected plug-ins:

com.jk.weather.sdPlugin:

20:19:48.608 main.js:221 WebSocket is already in CLOSING or CLOSED state.
request.onreadystatechange @ main.js:221
20:19:49.392 main.js:196 WebSocket is already in CLOSING or CLOSED state.
(anonymous) @ main.js:196

com.barraider.worldtime.sdPlugin:

20:18:39.059 worldtime.js:272 WebSocket is already in CLOSING or CLOSED state.
SetTitle @ worldtime.js:272

@ChekTek could you please take a look and suggest the proper solution? Thank you.

ChekTek commented 1 year ago

Hi! I was not able to reproduce the issue you are having.

Could you provide what version of Stream Deck you are using? I would recommend updating to the latest.

Do you have any custom sleep settings configured in Windows?

The com.jk.weather.sdPlugin and com.barraider.worldtime.sdPlugin do not use this template, in fact, very few use the template at all since it was only released very recently.

I will look into potentially implementing something similar to the code you proposed, as it could make the connection a bit more robust, but I'd like to understand the root cause of the issue.

CrazyCoder commented 1 year ago

@ChekTek Thanks for looking into this!

Could you provide what version of Stream Deck you are using? I would recommend updating to the latest.

I'm using the latest version: https://i.imgur.com/gEBdv4C.png. The issue occurs with this one and with 6.0.3 I used before. Didn't check with the other versions.

Do you have any custom sleep settings configured in Windows?

I don't think there is anything special in my setup on Windows 10 related to the power options. It looks like websocket becomes invalid/closes when the PC is going to sleep and is sometimes not restored when waking up. It may be specific to my machine, but I have no idea what could be the cause. I use OpenVPN for my work connection, but it should not affect localhost.

The com.jk.weather.sdPlugin and com.barraider.worldtime.sdPlugin do not use this template, in fact, very few use the template at all since it was only released very recently.

Yes, I know. I only recently found out that other plugins are also affected.

I will look into potentially implementing something similar to the code you proposed, as it could make the connection a bit more robust, but I'd like to understand the root cause of the issue.

I found another possible solution described at https://stackoverflow.com/a/23176223/104891. It connects the socket again once it's getting closed.

Thanks!

tiptronic commented 1 year ago

@CrazyCoder We don't see this behaviour in our own plugins, so there seems to also be a different problem... Atm. there's a simple workaround, by checking the systemDidWakeUp callback: https://developer.elgato.com/documentation/stream-deck/sdk/events-received/#systemdidwakeup Adding the proposed patch could be an improvement, but most likely the root of the problem is something else, otherwise the Websocket-connection should recover fine... Have you any chance to test that on a machine without OpenVPN? Maybe it's just a timing issue?