mikuso / ocpp-rpc

A Node.js client & server implementation of the WAMP-like RPC-over-websocket system defined in the OCPP-J protocols.
MIT License
94 stars 28 forks source link

Facing Issue for RPCGenericError: Assignment to constant variable #16

Closed kvext closed 2 years ago

kvext commented 2 years ago

Hi @mikuso,

Hope you're doing good!

I am trying to call one of method "StartTransaction" from server and want to receive response from client, but I am receiving error as below:

\node_modules\ocpp-rpc\lib\util.js:44
    const err = new E(message ?? '');
                ^

RPCGenericError: Assignment to constant variable.
    at createRPCError (D:\node_apps\node_ocpp_demo\node_modules\ocpp-rpc\lib\util.js:44:17)
    at RPCServerClient._onCallError (D:\node_apps\node_ocpp_demo\node_modules\ocpp-rpc\lib\client.js:841:25)
    at RPCServerClient._onMessage (D:\node_apps\node_ocpp_demo\node_modules\ocpp-rpc\lib\client.js:649:26)
    at WebSocket.<anonymous> (D:\node_apps\node_ocpp_demo\node_modules\ocpp-rpc\lib\client.js:369:42)
    at WebSocket.emit (node:events:527:28)
    at Receiver.receiverOnMessage (D:\node_apps\node_ocpp_demo\node_modules\ws\lib\websocket.js:1169:20)
    at Receiver.emit (node:events:527:28)
    at Receiver.dataMessage (D:\node_apps\node_ocpp_demo\node_modules\ws\lib\receiver.js:528:14)
    at Receiver.getData (D:\node_apps\node_ocpp_demo\node_modules\ws\lib\receiver.js:446:17)
    at Receiver.startLoop (D:\node_apps\node_ocpp_demo\node_modules\ws\lib\receiver.js:148:22) {
  rpcErrorMessage: '',
  rpcErrorCode: 'GenericError',
  details: {}
}

My Server Script as below:

const app = express();
const port = 3000;
const httpServer = app.listen(port, "localhost");
console.log(`OCPP Server started and listening on port ${port}...`);

const server = new RPCServer({
    protocols: ["ocpp1.6"],
    strictMode: false,
});
httpServer.on("upgrade", server.handleUpgrade);

server.auth((accept, reject, handshake) => {
    accept({
        sessionId: "XYZ123",
    });
});
server.on("client", async (client) => {
         client.handle(({ method, params }) => {
                console.log(`Server got ${method} from ${client.identity}:`, params);
            throw createRPCError("NotImplemented");
        });

       // Server Methods
       client.handle("BootNotification", ({ params }) => {
             console.log(
               `Server got BootNotification from ${client.identity}:`,
               params
            );
             return {
               status: "Accepted",
               interval: 300,
               currentTime: new Date().toISOString(),
            };
       });

         let resTrans = await client.call("StartTransaction", {
            connectorId: 0,
            idTag: "50-D6-BF-1A-D6-CC",
            meterStart: 20,
            timestamp: new Date().toISOString(),
        });
        console.log("Start Transaction Response: ", resTrans);
});

Client Script as below:

const app = express();
const httpServer = app.listen(3001, "localhost");

async function main() {
    const cli = new RPCClient({
        endpoint: "ws://localhost:3000",
        identity: "EXAMPLE123",
        protocols: ["ocpp1.6"],
        strictMode: false,
    });

    const transactionId = 0;

    cli.handle("StartTransaction", async ({ params }) => {
        if (params.idTag === "50-D6-BF-1A-D6-CC") {
            transactionId = Math.floor(Math.random() * 999999);
            return {
                idTagInfo: { status: "Accepted" },
                transactionId: transactionId,
            };
        } else {
            return { idTagInfo: { status: "Invalid" }, transactionId: -1 };
        }
    });

    cli.connect();

    try {

              let respBootNotification = await cli.call("BootNotification", {
                chargePointVendor: "ocpp-rpc",
                chargePointModel: "ocpp-rpc",
            });

            console.log(
               "Response from Server (BootNotification) => ",
               respBootNotification
           );
     } catch (err) {
        // Call failed
        console.error("Call failed because:", err.message);
        console.error("RPC Error code:", err.rpcErrorCode);
        console.error("Error details:", err.details);
        throw err;
    }
}

main().catch(console.error);     

Can you please provide me suggestion regarding to required to do changes on above?

Thanks,

mikuso commented 2 years ago

Hi,

Your client's StartTransaction handler is throwing an error. This, in turn, is causing your server to crash because you haven't handled the error there.

I suggest 2 changes for you:

1) In the client script, change const transactionId = 0; to let transactionId = 0;. This will fix your error.

2) In your server's 'client' event listener, you should probably add some error handling to prevent crashes. For example, wrapping the call in a try/catch block like so:

try {
    let resTrans = await client.call("StartTransaction", {
        connectorId: 0,
        idTag: "50-D6-BF-1A-D6-CC",
        meterStart: 20,
        timestamp: new Date().toISOString(),
    });

    console.log("Start Transaction Response: ", resTrans);

} catch (err) {
    // this catch block will prevent a crash
    console.error(`Error starting transaction:`, err);
}

Finally, you may also benefit from setting the option respondWithDetailedErrors: true in the constructors of both the client & server. This might help in future trying to pinpoint the cause of tricky errors like these; It will add a stack trace from the other side, showing you where the error originated from. (This should only be used for development purposes though, as it may be risky to expose this much information in a production environment.)

kvext commented 2 years ago

Hi @mikuso ,

Thanks a lot! It's working now.