skydiver / ewelink-api

eWeLink API for JavaScript
https://www.npmjs.com/package/ewelink-api
MIT License
264 stars 108 forks source link

websocket closes unexpectedly, causing Node Red to crash #231

Open mduchain opened 2 months ago

mduchain commented 2 months ago

Hello all, Today I noticed my NR was restarting almost every 3 minutes. The crash/restart was caused by an uncaught exception on timeout of the ping sent every 30s.

19 Apr 18:03:21 - [red] Uncaught Exception:
19 Apr 18:03:21 - [error] Error: Can't send data because WebSocket is not opened.
 at exports.throwIf (/x/.node-red/node_modules/websocket-as-promised/src/utils.js:4:11)
 at WebSocketAsPromised.send (/x/.node-red/node_modules/websocket-as-promised/src/index.js:248:5)
 at Timeout._onTimeout (/x/.node-red/node_modules/ewelink-api/src/mixins/openWebSocket.js:39:17)
 at listOnTimeout (node:internal/timers:559:17)
 at processTimers (node:internal/timers:502:7)

After digging a bit, noticed the connection was getting closed on the server side. Fiddling with the heartbeat timer didn't help (tried with 10s).

So, i fixed/patched it by catching the exception and restarting the connection. Offending original code, ewelink-api/src/mixins/openWebSocket.js

...
await wsp.open();
await wsp.send(payloadLogin);
setInterval(async () => {
      await wsp.send('ping');
}, heartbeat);

return wsp;

Patched code:

    ...
    await wsp.open();
    await wsp.send(payloadLogin);

    setInterval(async () => {
      try {
        await wsp.send('ping');
      } catch (error) {
        console.error('websocket-as-promised - heartbeat failed');
        await wsp.open();
        await wsp.send(payloadLogin);
      }
    }, heartbeat);

    return wsp;

This seems to have fixed it for me. Every now and then the connection drops, and at HB timeout the connection is re-established. Hope this helps.