Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

connection dropping afer one minute #80

Open
saimirg opened this issue Sep 1, 2024 · 4 comments
Open

connection dropping afer one minute #80

saimirg opened this issue Sep 1, 2024 · 4 comments

Comments

@saimirg
Copy link

saimirg commented Sep 1, 2024

Hi @mikuso, i need some help. I have a specific charger that is dropping connection after one minute. One the following simple code, the charger disconnects after one minute. However, if I connect the charger using the WS library the charger stays connected and i can communicate two ways.

This is the code used where the charger disconnects.


const server = new RPCServer({
    protocols: ['ocpp1.6'], // server accepts ocpp1.6 subprotocol
    strictMode: true,       // enable strict validation of requests & responses
});

server.auth((accept, reject, handshake) => {
    // accept the incoming client
    accept({
        // anything passed to accept() will be attached as a 'session' property of the client.
        sessionId: 'XYZ123'
    });
});

server.on('client', async (client) => {
    console.log(`${client.session.sessionId} connected!`); // `XYZ123 connected!`

    // create a specific handler for handling BootNotification requests
    client.handle('BootNotification', ({params}) => {
        console.log(`Server got BootNotification from ${client.identity}:`, params);

        // respond to accept the client
        return {
            status: "Accepted",
            interval: 300,
            currentTime: new Date().toISOString()
        };
    });
    
    // create a specific handler for handling Heartbeat requests
    client.handle('Heartbeat', ({params}) => {
        console.log(`Server got Heartbeat from ${client.identity}:`, params);

        // respond with the server's current time.
        return {
            currentTime: new Date().toISOString()
        };
    });
    
    // create a specific handler for handling StatusNotification requests
    client.handle('StatusNotification', ({params}) => {
        console.log(`Server got StatusNotification from ${client.identity}:`, params);
        return {};
    });

    // create a wildcard handler to handle any RPC method
    client.handle(({method, params}) => {
        // This handler will be called if the incoming method cannot be handled elsewhere.
        console.log(`Server got ${method} from ${client.identity}:`, params);

        // throw an RPC error to inform the server that we don't understand the request.
        throw createRPCError("NotImplemented");
    });

    // when clients disconnect, remove them from our Map
    client.once('close', () => {
        // check that we're about to delete the correct client
        console.log(`${client.session.sessionId} disconnected!`);
        console.log(`${client.identity} disconnected!`);

        // if (clients.get(client.identity) === client) {
        //     clients.delete(client.identity);
        // }
    });
});

await server.listen(3000);

Charger does not disconnect when using this code:

const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const bodyParser = require('body-parser');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

// Middleware
app.use(bodyParser.json());


// WebSocket handling for OCPP 1.6+
wss.on('connection', (ws) => {
  console.log('New WebSocket connection');

  ws.on('message', (message) => {
    const parsedMessage = JSON.parse(message);
    handleOCPPMessage(parsedMessage, (response) => {
      ws.send(JSON.stringify(response));
    });
  });
});

function handleOCPPMessage(message, callback) {
  const [messageType, messageId, action, payload] = message;

  switch (action) {
    case 'BootNotification':
      handleBootNotification(messageId, payload, callback);
      break;
    case 'StatusNotification':
      handleStatusNotification(messageId, payload, callback);
      break;
    default:
      callback([3, messageId, { error: 'NotImplemented' }]);
  }
}

function handleBootNotification(messageId, payload, callback) {
  console.log('Received BootNotification:', payload);
  const response = {
    status: 'Accepted',
    currentTime: new Date().toISOString(),
    interval: 300
  };
  callback([3, messageId, response]);
}

function handleStatusNotification(messageId, payload, callback) {
  console.log('Received StatusNotification:', payload);
  const response = {};
  callback([3, messageId, response]);
}

const PORT = process.env.PORT || 80;
server.listen(PORT, () => {
  console.log(`OCPP server listening on port ${PORT}`);
});```
@saimirg
Copy link
Author

saimirg commented Sep 10, 2024

Hi @mikuso, we found out the problem is with Pong response.
For some reasons Pong response from the charger is considered malformed and servers throws and error which drops the connection.
If we disable ping requests from the server everything works fine but this has an effect on other chargers.
We tried asking manufacturer to check the pong response but didnt succeed.

Anything else we can do to fix it ?

@mikuso
Copy link
Owner

mikuso commented Sep 11, 2024

Hi @saimirg

Were you able to recreate this issue using the WS library? What happens when the WS library receives a malformed pong?

One possible solution might be to set the pingIntervalMs option to Infinity when constructing the RPCServer, like so:

const server = new RPCServer({
    protocols: ['ocpp1.6'], // server accepts ocpp1.6 subprotocol
    strictMode: true,       // enable strict validation of requests & responses
    pingIntervalMs: Infinity, // disable pings
});

This should stop the server from sending pings, but disables the keepAlive functionality - so you may end up with lingering connections which get "stuck" if they don't cleanly disconnect.

@saimirg
Copy link
Author

saimirg commented Sep 11, 2024

Yes, the same behavior happens with WS library when initiating Ping from server side. An error will be thrown and connection would drop when pong is received.

Setting pingIntervalMs: Infinity (we tried null) will work on this particular charger but has an effect on other chargers. It would be great if we could set it on charger level rather then on server.

@mikuso
Copy link
Owner

mikuso commented Sep 11, 2024

Understood. Have you tried using client.reconfigure() to do this on an individual basis?

Something like...

server.on('client', client => {
    if (client.identity === 'badclient') {
        client.reconfigure({ pingIntervalMs: Infinity });
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants