Comments (6)
See #25 for some other suggestions on how to trap errors.
If the socket isn't open then it should return an error allowing the application to re-open the socket.
from ewelink-api.
Hi have the same problem, will be nice if you can change this
from ewelink-api.
NOTE: Currently testing on 3.1.0-ws, had to make a couple of additional changes, will post once fully tested.
I've added extra code to detect and report this issue back and terminate the app allowing the process manager to re-start.
pm2 logs
0|events | 2020-02-03T12:44:06.670Z | Socket closed...
0|events | 2020-02-03T12:44:06.670Z | Gracefully close and re-start...
PM2 | App [events:0] exited with code [1] via signal [SIGINT]
PM2 | App [events:0] starting in -fork mode-
PM2 | App [events:0] online
0|events | 2020-02-03T12:44:08.358Z | Started event monitor...
0|events | 2020-02-03T12:44:10.379Z | openWebSocketMixin:: heartbeat period in seconds: 120
0|events | 2020-02-03T12:44:10.667Z | Socket opened...
The events loop catches the socket closure and aborts the app, the process manager (pm2) catches this and re-starts:
$ pm2 ls
┌─────┬──────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼──────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ events │ default │ 1.0.0 │ fork │ 8650 │ 30h │ 2 │ online │ 0.5% │ 82.7mb │ sonoff │ disabled │
│ 2 │ scheduler │ default │ 1.0.0 │ fork │ 3892 │ 2D │ 0 │ online │ 0.5% │ 66.0mb │ sonoff │ disabled │
│ 1 │ www │ default │ 1.0.0 │ fork │ 3876 │ 2D │ 0 │ online │ 0.5% │ 60.6mb │ sonoff │ disabled │
└─────┴──────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Here you can see the event listener has been restarted twice because the connection was closed.
core event handler
socket = await connection.openWebSocket(async data => {
try{
if (data.action == "socket"){
switch (data.message) {
case "opened": console.log(new Date().toISOString(),'| Socket opened...');
break;
case "pong": //console.log(new Date().toISOString(),'| Keepalive received...');
break;
case "timeout": console.log(new Date().toISOString(),'| Socket timed out...');
case "closed": console.log(new Date().toISOString(),'| Socket closed...');
console.log(new Date().toISOString(),'| Gracefully close and re-start...');
case "error": socket.removeAllListeners();
socket.close();
process.exit(1);
throw new Error("timeout, closed or error...");
break;
default: console.log(new Date().toISOString(),'| socket action not supported,',"Invalid data::",JSON.stringify(data,null,4));
throw new Error("unknown...");
}
}else{
try {
if(data.action == "update"){
if((data.deviceid != null)&&(data.params.switch != null)){
console.log(new Date().toISOString(),'| device',data.deviceid,'alias',soo.localcache[data.deviceid].alias,'switch',data.params.switch);
post(www+'switch/'+data.deviceid+'/'+data.params.switch,'');
}
}
} catch (error) {
console.log(new Date().toISOString(),'| Caught error:',JSON.stringify(error));
}
}
} catch (error) {
console.log(new Date().toISOString(),'| Error returned:',error);
console.log(JSON.stringify(data,null,4));
socket.removeAllListeners();
socket.close();
process.exit(1);
throw new Error(error.message);
}
}).catch((error) => {
// Handle the error!
console.log(new Date().toISOString(),'| Final catch of Error returned:',error);
socket.removeAllListeners();
socket.close();
process.exit(1);
throw new Error(error.message);
});
ewelink-api/mixins/websocket/openWebSocketMixin.js
enhancements to catch and report errors. I've simplified after testing with 3.1.0-ws.
const W3CWebSocket = require('websocket').w3cwebsocket;
const WebSocketAsPromised = require('websocket-as-promised');
const wssLoginPayload = require('../payloads/wssLoginPayload');
module.exports = {
/**
* Open a socket connection to eWeLink
* and execute callback function with server message as argument
*
* @param callback
* @param heartbeat
* @returns {Promise<WebSocketAsPromised>}
*/
async openWebSocket(callback, ...{ heartbeat = 120000 }) {
const payloadLogin = wssLoginPayload({
at: this.at,
apiKey: this.apiKey,
appid: this.APP_ID,
});
const wsp = new WebSocketAsPromised(this.getApiWebSocket(), {
createWebSocket: wss => new W3CWebSocket(wss),
});
wsp.onMessage.addListener(message => {
if(message == "pong"){//eat pong...
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 () => {
if(wsp.isClosed || wsp.isClosing){
console.log(new Date().toISOString(),"wsp.isClosed || wsp.isClosing");
callback({"action": "socket" , "message" : "closed"});
}
//console.log(new Date().toISOString(),"ping sent...");
wsp.send('ping');//await
}, heartbeat);
return wsp;
},
};
This code now catches errors and passes them up to the calling code to deal with. The way I've delt with it is to just restart my event monitor, very simple and reliable.
When a ping is sent every 2min the socket stays open.
20|events | 2020-06-16T12:47:51.995Z | Started event monitor...
20|events | 2020-06-16T12:47:54.229Z | Socket opened...
20|events | 2020-06-16T12:49:54.228Z ping sent...
20|events | 2020-06-16T12:51:54.229Z ping sent...
20|events | 2020-06-16T12:53:54.231Z ping sent...
20|events | 2020-06-16T12:55:54.234Z ping sent...
20|events | 2020-06-16T12:57:54.235Z ping sent...
If I comment out sending the ping the code catches the socket timeout:
19|events | 2020-06-16T12:39:56.754Z | Started event monitor...
19|events | 2020-06-16T12:39:59.154Z | Socket opened...
19|events | 2020-06-16T12:41:59.155Z ping not sent...
19|events | 2020-06-16T12:42:39.246Z | Socket closed...
19|events | 2020-06-16T12:42:39.247Z | Gracefully close and re-start...
PM2 | App [events:19] exited with code [1] via signal [SIGINT]
PM2 | App [events:19] starting in -fork mode-
PM2 | App [events:19] online
19|events | 2020-06-16T12:42:40.857Z | Started event monitor...
19|events | 2020-06-16T12:42:43.103Z | Socket opened...
19|events | 2020-06-16T12:44:43.104Z ping not sent...
19|events | 2020-06-16T12:45:23.192Z | Socket closed...
19|events | 2020-06-16T12:45:23.193Z | Gracefully close and re-start...
from ewelink-api.
Any update on this issue?
from ewelink-api.
Hi
I still have this problem with the last version; Impossible to listen ewelink events with a long time
fix possible ?
from ewelink-api.
Hi.
I solve this issue by creating an auto restart mode in the openWebSocket.js when it closes the connection.
The ewelink-api/src/mixins/openWebSocket.js in this repository:
ewelink-api/src/mixins/openWebSocket.js
Lines 38 to 40 in 5a07f6b
I changed to get credentials and try to restart the WebSocket:
setInterval(async () => {
try {
await wsp.send('ping');
} catch (error) {
console.error(`openWebSocket.js: ${error}`);
console.log(`openWebSocket.js: Reconnecting...`);
const auth = await this.getCredentials();
const payloadLogin = wssLoginPayload({
at: auth.at,
apiKey: auth.user.apikey,
appid: this.APP_ID,
});
await wsp.open();
await wsp.send(payloadLogin);
}
}, heartbeat);
This way it closes the connection but doesn't close the process. It tries to connect again.
I'm still learning about JavaScript and I know that this code is very primitive, however, it solved my connection problem.
Feel free to make some changes.
from ewelink-api.
Related Issues (20)
- Install error
- Trouble with getDevicePowerUsage
- How do I know the type of device (Power meter, thermometer, etc.)? HOT 1
- Slow api, ETIMEDOUT, ECONRESET, ECONNREFUSED HOT 14
- problem with setInterval wsp.send('ping') openWebSocket.js HOT 1
- { error: 500, msg: 'SyntaxError: Unexpected token < in JSON at position 0' } HOT 1
- New and Simple REST API with Ready Scripts
- Error 401: Wrong account or password HOT 21
- ewelink
- Unable to install on Raspberry Pi
- THR316 doesn't update
- Unable to use power consumption with sonoff POW Elite HOT 6
- Get Voltage and current on POWR2 device HOT 2
- CoolkIt: Announcement regarding the expiration of the APPID referenced in this project and the cessation of maintenance of the v1 interface, suggesting migration HOT 7
- Error 401: Wrong account or password -- again HOT 54
- Error: 406 { error: 406, msg: 'Authentication failed' } HOT 21
- Support for changing the network indicator led?
- Is There Any PHP Version HOT 1
- error: 401, msg: 'Wrong account or password'
- Sonoff Dual R3 - Power Consumption Issue HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ewelink-api.