DRAFT — not indexed by search engines. Visible only via direct URL or the admin page.

Connect a Virtual Charge Point to Your CSMS (wss://)

Walk the OCPP boot handshake, station id, and subprotocol, then connect a virtual charge point to your CSMS live over wss:// — in the browser, no hardware.

Connecting a charge point to a CSMS sounds like it should be a hardware problem. It is not. From the backend’s point of view, a charging station is a WebSocket client that opens a secure connection, names itself, agrees on a protocol version, and then starts sending JSON. If you understand those four steps, you can connect a virtual charge point to your real CSMS from a browser tab and watch the whole handshake happen — which is exactly what Rey, the free browser-based virtual charge point, is built to do.

This article walks the connection step by step — the wss:// URL, the station id, the subprotocol, and the boot handshake — and then does it live against a CSMS. If you just want the hands-on version, open Rey, switch to “Connect my CSMS”, and follow along. If you are brand new to the protocol, what OCPP is gives you the big picture first.

The connection is just a WebSocket

OCPP 2.0.1 (and 1.6-J before it) runs as JSON over a single WebSocket. The charge point is the WebSocket client; the CSMS is the server. The station opens the connection, and it stays open for the life of the station — every heartbeat, status change, authorization, and transaction event travels over that one socket in both directions.

That has one important consequence for testing: anything that can open a WebSocket and speak the right handshake is, as far as your CSMS knows, a charge point. It does not matter whether the frames come from firmware on a wall-mounted unit in a car park or from JavaScript in a browser tab. This is why software emulation covers almost all backend testing — a point we go deeper on in testing an OCPP charge point without hardware (coming soon).

So the whole job of “connecting” comes down to getting four things right in the WebSocket upgrade. Let us take them in order.

Step 1: The wss:// URL and the station id

The endpoint is the CSMS’s secure WebSocket URL, with the station identity as the final path segment:

wss://csms.example.com/ocpp/CP001

Two things matter here. First, wss:// — not ws:// — is WebSocket over TLS. Production CSMS endpoints are almost always wss://, and OCPP Security Profiles 2 and 3 require it. Plain ws:// shows up only on local test rigs.

Second, CP001 is the station id (OCPP calls it the charging station identity). It is not decoration — the CSMS reads it straight out of the URL path to decide which station just connected, before a single OCPP message is exchanged. It has to match an identity the CSMS was provisioned with. Get it wrong and a well-behaved CSMS rejects the upgrade outright; a lax one may accept the socket and then reject the BootNotification. Either way, a mismatched station id is one of the most common reasons a connection that “looks fine” never boots.

Step 2: The subprotocol (ocpp2.0.1)

WebSocket has a built-in mechanism for negotiating what will be spoken over the socket: the Sec-WebSocket-Protocol header. OCPP uses it to pin the version. The charge point advertises one or more of:

  • ocpp1.6 — OCPP 1.6-J
  • ocpp2.0.1 — OCPP 2.0.1
  • ocpp2.1 — OCPP 2.1

The CSMS must echo back exactly one of the offered subprotocols in its 101 Switching Protocols response. If the CSMS and station share no common version, the CSMS is supposed to not select a subprotocol and close the connection — it should never silently accept a socket and then guess. In practice, if you point a 2.0.1 station at a 1.6-only backend, this is where it breaks, and the symptom is a socket that opens and immediately closes with no OCPP messages at all.

This negotiation is invisible in most logs unless you go looking, which is why a tool that surfaces the chosen subprotocol saves real debugging time.

Step 3: Authentication over TLS

wss:// gives you the encrypted transport; it does not, by itself, prove who the station is. That is what OCPP’s security profiles (coming soon) handle, and which one your CSMS uses determines what you supply at connection time:

  • Profile 1 — HTTP Basic auth in the WebSocket upgrade request. The username is the station id; the password is the BasicAuthPassword the CSMS was configured with.
  • Profile 2 — the same Basic auth, but now over server-side TLS (wss:// with a CSMS certificate your client trusts).
  • Profile 3 — mutual TLS: the station presents its own client certificate instead of a password, and the CSMS verifies it.

For a virtual charge point, Profiles 1 and 2 are the everyday cases — you supply the station id and the Basic-auth password, and the CSMS validates them during the upgrade. There is a catch that trips people up immediately: browsers deliberately forbid setting the Authorization header (or any custom header) on a WebSocket. That is a browser security rule, not an OCPP one. Rey works around it with a small relay that presents the Basic-auth header the browser cannot, so a browser tab can still authenticate to a real wss:// CSMS exactly as firmware would.

Step 4: The boot handshake

Once the socket is open, authenticated, and speaking an agreed version, the station has to introduce itself before it is allowed to do anything else. It sends BootNotification, and the CSMS replies with a status:

  • Accepted — you are provisioned; here is your heartbeatInterval; carry on.
  • Pending — I know you, but I am not ready; keep retrying at the interval I give you.
  • Rejected — go away and retry later.

Nothing else happens until BootNotification returns Accepted. No StatusNotification, no Authorize, no transaction. A station stuck re-sending BootNotification and getting Pending or Rejected is the number-one “it connects but nothing works” symptom, and it is almost always a provisioning mismatch — the station id or model the station reports does not line up with what the CSMS expects. The full field breakdown and every failure mode live in the BootNotification message (coming soon).

On the wire, the request is a plain JSON array — [2, "unique-id", "BootNotification", { ... }] — and the CSMS answers [3, "unique-id", { "status": "Accepted", "interval": 300, ... }]. Once you have seen this exchange a few times you can read it straight off a network tab.

Do it live in Rey

Here is where the four steps stop being theory. Rey is a virtual OCPP 2.0.1 charge point that runs entirely in the browser, and it does precisely what we just walked through:

  1. Open Rey and choose “Connect my CSMS”.
  2. Paste your CSMS’s wss:// URL, set the station id, and add the Basic-auth password if your backend uses one.
  3. Rey opens the real WebSocket, negotiates the ocpp2.0.1 subprotocol, presents the auth via its relay, and sends BootNotification.
  4. Confirm the CSMS returns Accepted, then run a full session — Authorize, a TransactionEvent from Started through metered Updated frames to Ended — and inspect every OCPP-J array as it moves.

Because Rey shows each frame as its real wire array, you can copy any of them out as test fixtures, or diff them against the traffic from your production chargers. And it works against any conformant CSMS, whether that is your own build, a commercial platform, or one of the open-source stacks below. No firmware, no lab, no hardware on your desk.

If you would rather learn the flow first

If the message sequence is still fuzzy, do not start by connecting a live backend — start by watching a healthy conversation end to end. The canned OCPP simulator replays a full session frame by frame so you can learn the order and the field names passively, with nothing to configure. Then come back to Rey to test your CSMS live. Learn the flow in the simulator; exercise your backend in Rey.

Where open-source stacks fit

You may be connecting to an open-source CSMS, or you may be comparing your build against one. A few worth knowing, kept balanced across the ecosystem:

  • CitrineOS — an open-source CSMS authored by S44 (North America) and hosted by LF Energy, under the Apache 2.0 license. It is OCPP 2.0.1 certified by the Open Charge Alliance and also supports 1.6. A natural wss:// target to point Rey at.
  • SteVe — a long-running open-source CSMS in Java (originating at RWTH Aachen in Germany), community-maintained since 2013 under GPLv3, focused on OCPP 1.6. Widely used as a reference backend.
  • EVerest — an LF Energy charge-point firmware stack (initiated by Pionix, Germany), Apache 2.0, whose libocpp implements OCPP 1.6, 2.0.1, and 2.1. This is the station side, not a CSMS.
  • MicroOcpp — a lightweight OCPP 1.6 / 2.0.1 client for microcontrollers, MIT-licensed. Again the station side, aimed at constrained firmware.

The pattern to notice: SteVe and CitrineOS are servers you connect to; EVerest and MicroOcpp are the charge-point side you would otherwise need to emulate. A browser virtual charge point stands in for that station side against any of the server-side backends, in exactly the same way regardless of whether the CSMS is running in a data centre in Frankfurt or Toronto — OCPP is deliberately vendor- and region-neutral.

The connection, in one line

Connecting a charge point to a CSMS is four things done in order: a wss:// URL carrying the station id, an ocpp2.0.1 subprotocol both sides agree on, auth appropriate to the security profile, and a BootNotification that comes back Accepted. Get those right and everything else is just messages on an open socket. The fastest way to prove your CSMS handles all four correctly is to connect Rey to it and watch — free, in the browser, right now.

Frequently asked questions

How do I connect a charge point to a CSMS?

A charge point connects to a CSMS by opening a WebSocket to the CSMS's wss:// endpoint, with the station id as the final path segment of the URL and the OCPP version advertised in the Sec-WebSocket-Protocol header. Once the socket is open it sends BootNotification, and the CSMS replies Accepted, Pending, or Rejected. You can do exactly this from a browser with a virtual charge point — no firmware or hardware required.

What is the wss:// URL for an OCPP charge point?

It is the CSMS's secure WebSocket endpoint with the station identity appended as the last path element — for example wss://csms.example.com/ocpp/CP001, where CP001 is the station id the CSMS was provisioned with. wss:// means WebSocket over TLS, which is required for OCPP Security Profiles 2 and 3.

What subprotocol does OCPP use over WebSocket?

The charge point advertises the OCPP version in the Sec-WebSocket-Protocol header — ocpp1.6 for OCPP 1.6-J or ocpp2.0.1 for OCPP 2.0.1. The CSMS must echo back exactly one of the offered subprotocols in its upgrade response. If it selects none, the connection should be treated as failed rather than left open.

Can I test a wss:// CSMS connection from a browser?

Yes. Rey is a browser-based virtual charge point that opens a real OCPP connection — pick OCPP 1.6, 2.0.1, or 2.1 — to your CSMS over wss://. Because browsers cannot set Basic-auth or custom headers on a WebSocket, it uses a relay to present those headers, then runs a full boot, authorize, and transaction so you can watch how your backend responds.

Found this useful? Share it.