Code Monkey home page Code Monkey logo

Comments (16)

foulek57 avatar foulek57 commented on May 24, 2024 1

Hello,

Sorry, was not your code, have no error with your code, work nice !!
You can add it to the openWebSocket.

I take this opportunity to say congratulations for your work!

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024 1

Martin,

In order to keep the pong reply I return a sonoff type structure with the action being socket, eg:

    wsp.onMessage.addListener(message => {
      if(message == "pong"){
        callback({"action" : "socket" , "message" : "pong"});
        ////////////////////////////////////////////////////////////////
      }else{
        try {
          const data = JSON.parse(message);
          callback(data);
        } catch (error) {
          callback(message);
        }
      }
    });

In the calling code I now use:

    socket = await connection.openWebSocket(async data => {
        try{
            if (data.action == "socket"){
                date = new Date().toUTCString();
                switch (data.message) {
                case "opened":  console.log("### Socket opened at:",date);
                                break;
                case "pong":    //console.log("### keepalive received at:",date);
                                break;
                case "error":
                case "closed":  console.log("### Socket closed at",date,"\n\tgracefully close and re-open socket...");
                                break;
                default:        console.log("### socket action not supported at",date,"Invalid 
                }
            }else{
                console.log("data::",JSON.stringify(data,null,4));  //if(DEBUG) when coded !
            }
        } catch (error) {
            console.log("Invalid data::",JSON.stringify(data,null,4));  //if(DEBUG) when coded !
        }

I've also returned other states, eg socket opened, closed or error, I'll do a little more testing and then post the changes.

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Using 1.8.1 I've tried:

async function main () {
const login = await connection.login(account);//login to server
// call openWebSocket method with a callback as argument
socket = await connection.openWebSocket(async data => {
// data is the message from eWeLink
console.log(data)
});
}

NEVER stays open for more than 2 minutes and 42-44 seconds, sometimes much less.

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

Have that same problem

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Same in 1.8.2 . . .

from ewelink-api.

skydiver avatar skydiver commented on May 24, 2024

Hey guys:

This is the library used for websocket https://github.com/vitalets/websocket-as-promised

I didn't see anything related to timeout.

Maybe the service needs to be pinged every x minutes to keep connection open?

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

Hello have search today, the websocket as promised have the timeout 0 sa default, have add a onClose to my script and the result are "Connections closed: Connection dropped by remote peer." but find no result on google ... Any idea guys ?

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

I have read on the web that the connection are close beacause we need to ping it, have try to send a switchDevice command every 15 sec and the server not close the conection.
Any idea how to do the ping ?
I have try socket.send('ping'); seem to work but have a error
pong
^
SyntaxError: Unexpected token p in JSON at position 0
at JSON.parse ()
at /var/www/html/plugins/ewejee/core/js/node_modules/ewelink-api/mixins/websocket/openWebSocketMixin.js:26:25
at Timeout._onTimeout (/var/www/html/plugins/ewejee/core/js/node_modules/websocket-as-promised/dist/index.js:1240:38)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)

from ewelink-api.

skydiver avatar skydiver commented on May 24, 2024

Guys, this worked for me:

First, update openWebSocketMixin.js, and replace:

    wsp.onMessage.addListener(message => {
      const data = JSON.parse(message);
      callback(data);
    });

with:

    wsp.onMessage.addListener(message => {
      try {
        const data = JSON.parse(message);
        callback(data);
      } catch (error) {
        callback(message);
      }
    });


Then on your script, add this code:

(async () => {

  const connection = new ewelink({
    email: '<your email>',
    password: '<your password>',
    region: '<your region>'
  });

  await connection.login();

  const socket = await connection.openWebSocket(async data => {
    // data is the message from eWeLink
    console.log(data);
  });

  const interval = setInterval(async () => {
    await socket.send('ping');
  }, 90000);

})();

If this work for you, i will move the ping command inside the openWebSocket method so nobody needs to worry about sending the heartbeat to the server.

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

Hi, yesterday I have tried to ping with interval of 60000ms this have work all the night.

I have detect the "pong" before the json.parse so I have no error.

I will try your change and confirm if this work by me.

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

Hello,

Have tryed your code, but have an error :

(node:14130) UnhandledPromiseRejectionWarning: Error: Can't send data because WebSocket is not opened.
at exports.throwIf (/var/www/html/plugins/ewejee/core/js/node_modules/websocket-as-promised/dist/index.js:3470:11)
at WebSocketAsPromised.send (/var/www/html/plugins/ewejee/core/js/node_modules/websocket-as-promised/dist/index.js:554:7)
at Timeout._onTimeout (/var/www/html/plugins/ewejee/core/js/newserver.js:62:20)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
(node:14130) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Hi, yesterday I have tried to ping with interval of 60000ms this have work all the night.

I have detect the "pong" before the json.parse so I have no error.

I will try your change and confirm if this work by me.

Perhaps 120s (120000ms) to reduce traffic as it appears the time out is 160s.

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Using release_1.10.0

Left an event monitor running overnight, looks like it crashed. I'm guessing the socket closed and the ping then fails:

    at ontimeout (timers.js:482:11)
    at tryOnTimeout (timers.js:317:5)
    at Timer.listOnTimeout (timers.js:277:5)
(node:21254) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 235)
(node:21254) UnhandledPromiseRejectionWarning: Error: Can't send data because WebSocket is not opened.
    at exports.throwIf (~/node_modules/websocket-as-promised/dist/index.js:3470:11)
    at WebSocketAsPromised.send (~/node_modules/websocket-as-promised/dist/index.js:554:7)
    at Timeout.setInterval [as _onTimeout] (~/node_modules/ewelink-api/mixins/websocket/openWebSocketMixin.js:38:17)

Need to detect the socket closes and re-open it.
I've restarted and date stamped the output to see how long it goes before it crashes.

I'll leave it till tomorrow to see if it drops itself before I disable access to coolkit.cc which will simulate dropping the connection.

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Make sure .close() is called before application terminates otherwise restarting application may not connect 1st time.

In main application I have:

var socket;	//define outside of asyn function to allow access as required
process.on("SIGINT", () => {
	console.log(" - Caught SIGINT. Exiting in 3 seconds.");
	console.log("Closing WebSocket...");
	var cls = socket.close();
	setTimeout(() => {
		process.exit(0);
	}, 3000);
});

So if the process is terminated it will close the web socket. Since adding this the app has gracefully closed the socket every time and always restarts 1st time.

from ewelink-api.

foulek57 avatar foulek57 commented on May 24, 2024

Hi dear,

This is a good idea, the pong message are for me important, so I can detect that all is ok.

Thanks for your job !

from ewelink-api.

ttz642 avatar ttz642 commented on May 24, 2024

Once the events listener starts it is likely to hang up at some point due to lost socket connection. I've made changes to the library to catch some of the conditions that result in the connection failing and the code just hanging up.

Changes to openWebSocketMixin.js to catch communication errors more gracefully.

Changed heartbeat to 6s just to speed up debug.

Event loop (main):

    socket = await connection.openWebSocket(async data => {
        try{
            if (data.action == "socket"){
                date = new Date().toUTCString();
                switch (data.message) {
                case "opened":  console.log("### Socket opened at:",date);
                                break;
                case "pong":    console.log("### keepalive received at:",date);
                                break;
                case "timeout": console.log("### Socket timed out at",date);
                case "closed":  console.log("### Socket closed at",date);
                                console.log("gracefully close and re-open socket...");
                case "error":   throw new Error("timeout...");
                                break;
                default:        console.log("### socket action not supported at",date,"Invalid data::",JSON.stringify(data,null,4));
                                throw new Error("unknown...");
                }
            }else{
                console.log("data::",JSON.stringify(data,null,4));
            }
        } catch (error) {
			console.log("Error returned:",error);
            console.log(JSON.stringify(data,null,4));
			process.exit(2);
        }
    })

Changes to openWebSocketMixin.js, replace:

    wsp.onMessage.addListener(message => {
      try {
        const data = JSON.parse(message);
        callback(data);
      } catch (error) {
        callback(message);
      }
    });

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

with:

    wsp.onMessage.addListener(message => {
      if(message == "pong"){//eat pong...
        tsin =  Math.floor(Date.now()/1000);
        callback({"action" : "socket" , "message" : "pong"});
        ////////////////////////////////////////////////////////////////
      }else{
        try {
          const data = JSON.parse(message);
          callback(data);
        } catch (error) {
          callback(message);
        }
      }
    });

    wsp.onOpen.addListener(() => {
        callback({"action": "socket" , "message" : "opened"});
    });
    wsp.onClose.addListener(event => {
        callback({"action": "socket" , "message" : "closed"});
    });
    wsp.onError.addListener(event => {
        callback({"action": "socket" , "message" : "error"});
    });
    await wsp.open();
    await wsp.send(payloadLogin);
    setInterval(async () => {
      var tsdelta = tsout - tsin;
      console.log("tsdelta",tsdelta);
      if(wsp.isClosed){
        callback({"action": "socket" , "message" : "closed"});
      }
      if(tsdelta >= (period*5)){
        //if we haven't had a reply to one of the three outstanding ping's
        //in last 5 heartbeats were probably not connected anymore, thus timeout
        callback({"action": "socket" , "message" : "timeout"});
      }
      tsout =  Math.floor(Date.now()/1000);
      if(tsdelta < (3 * period)){
        wsp.send('ping');//await
        var date = new Date().toUTCString();
        console.log("### keepalive sent at:",date);
      }
    }, heartbeat);

Running the code:

$ bin/events.js
openWebSocketMixin...
heartbeat period in seconds: 6
### Socket opened at: Wed, 27 Nov 2019 11:55:34 GMT
data:: {
    "error": 0,
    "apikey": "45b2b2ba-037e-4819-8ee5-09553a6f2119",
    "config": {
        "hb": 1,
        "hbInterval": 145
    },
    "sequence": "1574855733875"
}
tsdelta 0
### keepalive sent at: Wed, 27 Nov 2019 11:55:40 GMT
### keepalive received at: Wed, 27 Nov 2019 11:55:40 GMT  <<== last pong received

**INTERNET CONNECTION DISABLED**

tsdelta 0
### keepalive sent at: Wed, 27 Nov 2019 11:55:46 GMT  <<== 1st ping after lost connection
tsdelta 6
### keepalive sent at: Wed, 27 Nov 2019 11:55:52 GMT  <<== 2nd ping after lost connection
tsdelta 12
### keepalive sent at: Wed, 27 Nov 2019 11:55:58 GMT  <<== 3rd ping after lost connection
tsdelta 18
tsdelta 24
tsdelta 30  <<== 5th pong missing, signal timeout
### Socket timed out at Wed, 27 Nov 2019 11:56:16 GMT
### Socket closed at Wed, 27 Nov 2019 11:56:16 GMT
gracefully close and re-open socket...
Error returned: Error: timeout...
    at connection.openWebSocket (/home/steve/ewelink-api/bin/events.js:56:39)
    at Timeout.setInterval [as _onTimeout] (/home/steve/ewelink-api/node_modules/ewelink-api/mixins/websocket/openWebSocketMixin.js:77:9)
    at ontimeout (timers.js:482:11)
    at tryOnTimeout (timers.js:317:5)
    at Timer.listOnTimeout (timers.js:277:5)
{
    "action": "socket",
    "message": "timeout"
}

I'll use PM2 to handle restarting the process...

from ewelink-api.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.