Comments (3)
Hi - as I said, it's possible that you simply missed the opportunity to subscribe to the close event before the socket closed.
Please re-read the second half of my post.
There should not be any scenarios where a 'close'
event is not sent.
from ocpp-rpc.
Hi sarin,
Thanks for the kind words.
It looks like there are two possible race conditions that could arise as a result of the code snippet you've provided. Allow me to explain how these can occur:
Charge point connected but showing offline in DB.
Imagine the following scenario:
- Charger XYZ connects to the server (let's call this Session 1).
- Server updates the database to reflect the charger being online.
- The charger disconnects uncleanly (i.e. no TCP FIN is received by the server - perhaps a cable was unplugged) so we have to wait for an idle ping timeout before the server recognises that the charger has disconnected.
- The charger XYZ reconnects to the server (Session 2) before the server realises that Session 1 has ended.
- The server once again updates the database to reflect that the charger is online.
- The original connection (Session 1) finally succumbs to ping timeout and the connection is dropped from the server side.
- The server updates the database to indicate that the charger is now offline, despite the fact that Session 2 is still online.
Here's one way you could address this problem:
Inside the RPCServer's auth
handler, assign a unique session ID to the client and pass it to the accept()
callback like so:
const {randomBytes} = require('crypto');
server.auth((accept, reject, handshake) => {
const session = {};
// create a random session ID and assign it to the session object
session.id = randomBytes(16).toString('hex');
// accept the client connection and assign the session object to the client
accept(session);
});
You can then use this ID to ensure that you are only determining the charge point to be offline when the most recent session comes to an end.
So... to apply this to your code:
server.on("client", async (client) => {
await db("chargepoints")
.where({ id: client.identity })
.update({
online: true,
sessionId: client.session.id
});
client.once("close", async () => {
await db("chargepoints")
.where({
id: client.identity,
sessionId: client.session.id
})
.update({ online: false });
});
});
This will ensure that only the termination of the most recent session would be able to flag the charger as being offline.
Another edge case to keep in mind is what would happen if you have 2 chargers connected to the server using the same identity. Something for you to think about.
Charge point is disconnected but still marked as online in DB.
This could occur if the charger has disconnected very quickly after connecting. This could be caused by a failing proxy, a bug in the firmware, or some other unusual condition.
Imagine this scenario:
- Charger XYZ connects, triggering your RPCServer's
'client'
event. - You begin to update your database to reflect that the charger is online. This could have a variable latency (eg. maybe 50ms before the Promise resolves).
- During this 50ms, the charger disconnects, firing the
'close'
event on the client. - Once the database has been updated, you then start listening for the
'close'
event on the client, but it is now too late as the client has already disconnected. - The client's
'close'
event will not fire again, so you will never record that the charger has gone offline.
The solution here is to start listening for the 'close'
event before performing any async operations (such as updating the database). It's actually a good idea to start listening for all events you are interested in before you start doing any async operations, as you may miss events firing if you are stuck waiting on your database to respond.
I hope this helps.
from ocpp-rpc.
Hi Mikuso, thanks for the explanation & suggestions.
We were not aware of the possible multiple sessions. So the first issue can be solved as you suggested. But for the second issue, we never received a 'close' event. Are there any scenarios where the charger disconnects without a 'close' event?
from ocpp-rpc.
Related Issues (20)
- Feat: RPCClient should take an AbortSignal as a constructor option to close() on abort
- Wildcard handler HOT 2
- Module Not Found HOT 4
- Handshake with the same Charging point keeps on happening again and again. HOT 14
- How do StartTransactions work HOT 2
- Correct way to send a handshake or connect HOT 3
- Difficulty Setting Charging Profile After Clearing an Existing Profile for Dynamic Load Balancing HOT 2
- RPCServer 'upgradeAborted' event can fire after websocket upgrade is successful HOT 1
- Central system microservice HOT 7
- Backend to OCPP server communication via WebSocket (sendRaw) HOT 7
- Example for using this package in a project that uses ESM module HOT 4
- Correct way to set the maximum watt a charger can charge in a RemoteStartTransaction. HOT 28
- Disconnects after 30 sec HOT 3
- Error While Disconnecting from Webscoket Client HOT 5
- WebSockerPingInterval HOT 1
- BootNotification - StatusNotification works fine but can not StartTransaction
- Cannot use RPCServer. Maybe it is caused the 'Ajv' module was updated to version 8.15, which lacks the necessary compatibility. HOT 1
- Unable to start server with await HOT 5
- Getting Client Identity from the URL and not from the handshake.identity HOT 4
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 ocpp-rpc.