How to use OCPP in Node-Red

@nygma2004 Did you manage to get RemoteStartTransaction working?

No, I did not. Honestly I was waiting for some suggestion on what I have done wrong, or what how should I try different.
And unfortunately I am not able to VPN into the place were it is installed, so can't test right now.

Thats what I use to schedule start/stop for charging my car.

Sorry I still haven't tidied up my flows (they are a working mess, intertwined with cron scheduling from 30 min block electrickery rates from octopus agile) - you are welcome to a copy of what I have (but only via DM - as they need tidy up work before being presented as usable to a passer-by on the forum)

3 Likes

Yes please Steve.
I'm not too bothered about the octopus agile stuff, but I'd like to see how you've structured your commands that interact with your charger.

As my charger is solar compatible, I'm wanting to divert exported solar power to the charger.
I'm using Monta at the moment, which works fine for normal charging, but it performs poorly when diverting solar. Monta tech support haven't been much use...

ok, since @Paul-Reed and @nygma2004 have asked, I took a little time to tidy up the flows.

Nodes used:

  • "node-red-contrib-ocpp": "1.3.6" (or greater) (required)
  • "node-red-contrib-cron-plus": "2.1.0" (or greater) (required for scheduling)
  • "@sammachin/node-red-matter-bridge": "0.12.0" (or greater) (optional matter device - for "hey google/alexa/siri, turn the ev charger on"
  • "@flowfuse/node-red-dashboard": "1.22.1" (or greater) (optional, for dashboard control)

The dashboard looks like this:

Flows: evse-demo.json (105.0 KB)

3 Likes

Thanks a lot, this is very helpful, although I think tried the same myself.

From your flow, I copied over these 3 nodes to test the simple GetDiagnostics request.
All I did is replaced the configuration on the CS request JSON node to my Charge Box ID. When I deploy the flow I see this:

I triggered the inject node, and I see this:

Why is this happening? This is why I got stuck with RemoteStartTransaction as well, because nothing seems to be executed.

And I am pretty sure the ID is correct, because I see that in the Heartbeat message in the debugger:

And the configuration is like this:

What am I missing here?

Hey! I’ve been looking into OCPP integration in Node-RED too, and yeah... it’s definitely not super straightforward out of the box.

I came across a few community nodes like node-red-contrib-ocpp but they seem either outdated or not actively maintained. What worked best for me was using a WebSocket client node in combination with some custom logic to handle the OCPP JSON messages manually. It’s a bit more hands-on, but you get more control that way.

You’ll probably need to mimic the heartbeat, boot notification, and other standard messages depending on if you're simulating a charge point or managing a backend.

If anyone’s got a more plug-and-play approach or a node that’s currently maintained, I’d love to hear about it too!

2 Likes

I will try to give the occp nodes a try, it worked for Steve so I am hopeful. I just started a holiday now, so this has to wait a bit.

Finally taken the plunge using @Steve-Mcl 's flow, however, although it initially connects, the charger disconnects almost immediately. I suspect because it's not getting a response from the flow, due to the OCPP CS Command Switch not recognising "OnlineNotification".

This is the ocpp log;

22/04/2025, 09:25:33     node: BS5444466@8082    type: info      data: Ready to recieve websocket requests on //:cbid
22/04/2025, 09:26:11     node: BS5444466@8082    type: info      data: Ready to recieve websocket requests on //:cbid
22/04/2025, 09:29:05     node: BS5444466@8082    type: info      data: Ready to recieve websocket requests on /ocpp/:cbid
22/04/2025, 09:29:07     node: BS5444466@8082    type: info      data: Websocket connecting to chargebox: BS542T766

...and the debugs

  1. Node incoming
{
  "ocpp": {
    "websocket": "ONLINE",
    "chargeBoxIdentity": "BS5444466"
  },
  "_msgid": "e05afd59e40211b0"
}
  1. msg
{
  "ocpp": {
    "websocket": "ONLINE",
    "chargeBoxIdentity": "BS5444466"
  },
  "_msgid": "e05afd59e40211b0",
  "ocppData": {
    "websocket": "ONLINE",
    "chargeBoxIdentity": "BS5444466",
    "payload": {},
    "command": "OnlineNotification"
  },
  "topic": "OnlineNotification"
}
  1. Unsupported
{
  "ocpp": {
    "websocket": "ONLINE",
    "chargeBoxIdentity": "BS5444466"
  },
  "_msgid": "e05afd59e40211b0",
  "ocppData": {
    "websocket": "ONLINE",
    "chargeBoxIdentity": "BS5444466",
    "payload": {},
    "command": "OnlineNotification"
  },
  "topic": "OnlineNotification"
}

OnlineNotification is apparently part of the Boot Notification process - so perhaps you have to add that and respond?

My unit either doesnt send that (or doesnt care)


Add OnlineNotification to the switch and hook it up to the "Generic Status=Accepted" or the "BootNotification" path


EDIT:

I remember now. OnlineNotification is something I added for personal clarity. Whats happening is the WS is coming "ONLINE" (transport is connecting). This does not warrant a reply to the charger.

Expected OCPP Flow

Once the WebSocket is ONLINE:

  1. The Charge Point should send a BootNotification request (in OCPP 1.6 and 2.0.1). This is the first formal message in the OCPP lifecycle.
  2. Your server should respond with a BootNotification.conf, including status (Accepted/Rejected), interval, etc.

Until this exchange is completed properly, the charger may close the connection or retry.

Are you seeing the BootNotification ever?

Another thought. You might be getting a GetConfiguration in the heartbeat which warrants a different response

Have a look at the example
image

PS, ChatGPT can help you solve this (it is fairly knowledgeable on OCPP - it even offered to diagnose a trace of WebSocket frames!)

Looking into the flow above, I'm wondering if we could use a hardcoded 'idTag', instead of one randomly generated by the charger?
If we could, it would simplify the flow, help debugging, and possibly be more robust?

I asked ChatGPT;
"Why can't I use a hardcoded value like "MYTAG" in a live environment, as there will only ever one user and one device starting a charging session?"

That’s a totally fair question — and actually, in many cases you can use a hardcoded idTag like "MYTAG" if:

  • Your setup is simple and local (e.g., one charger, one user, no billing/auth)
  • You are using a custom OCPP backend (like your Node-RED system)
  • The charger doesn’t enforce strict authorization rules or is configured to accept all tags

:brain: But in your case?

You’re running this via Node-RED, possibly offline or with minimal user variation. So using a fixed idTag like:

"idTag": "MYTAG"

...is absolutely fine.


I've tried it, and it appears to work fine, with no error messages.

Thoughts??

I forget where I got to with tags and auth, but I think you can setup allowable tags and use a Auth command.

from my export:

I also think in your charger you can disable tag auth? (allow any?)

I think the issue you might have by using hard coded value is if you start your charger with a tag (RFID) then the global wont be updated and the Remote Stop might not work.

However if it all works for you it works!

I didn't look in there, as it was titled 'Untested' !

But just done a charge and the transactionId was recorded OK, and it stopped fine, again, no errors.
Really pleased that you shared the flow @Steve-Mcl, it's given me a big start :grinning_face_with_smiling_eyes:

Next on my list is to limit the charging current to match surplus solar energy.

I don't get it. I think I am doing everything the same as you, and still nothing happens.
I get the Heartbeat messages and the StatusNotifications from the CPs, but when I try to a GetConfiguration. I don't see any message coming from CS server node, not even an OnlineNotification. The CS->CP side of the communication is simply not working...
And I am not seeing anything in the logs either.

I did some more investigation, understanding Paul's flow.
I understand now that you are converting the special messages where only websocket = "ONLINE" and websocket = "OFFLINE" messages are recieved and how you are converting them to Onlinenotification and Offlinenotification commands.
I did the same with some minor changes (not saving the data to msg.ocppData).
And I also handle these cases in the OCPP CS Command Switch (red marks on the screenshot) and responding to these with a Generic Status=Accepted message.

But still, what I noticed that I get the ONLINE messages from all 3 CP, after that I get a StatusNotification that they are available, and after about 10-20 seconds, all 3 CP send an "OFFLINE" message as well. But they keep sending a Heartbeat from that point onwards.

This probably explains why the CPs are not responding to the CS request.
But still, what did I miss? In Paul's flow, I don't see a response to the online notification either. So why my CPs are going offline?