OCPP
OCPP (Open Charge Point Protocol) is the protocol between an EV charging station and the system that manages it. The Open Charge Alliance (OCA) publishes it, with a JSON schema for every message. This page explains OCPP-J, OCPP over WebSocket with JSON, in the three versions the OT Fabric projects implement: 1.6J (with the Security Whitepaper extensions), 2.0.1 and 2.1.
The two roles
Section titled “The two roles”| Role | OCPP 2.x name | OCPP 1.6 name | In go-ocpp |
|---|---|---|---|
| The charger | Charging Station | Charge Point | package client |
| The management system | CSMS (Charging Station Management System) | Central System | package server |
The station is always the WebSocket client: it opens the connection to the CSMS, so a charger behind a mobile router or NAT can be managed. Once the connection is open, both sides send requests. The station boots, authorizes cards, reports transactions and sends meter values; the CSMS starts and stops sessions remotely, sets charging limits, reads and writes configuration, and triggers firmware updates and log uploads.
Connecting
Section titled “Connecting”The station connects to the CSMS’s endpoint with its own identity as the last path segment:
wss://csms.example.com/ocpp/CS001In the WebSocket handshake it offers the versions it speaks as subprotocols (ocpp2.1, ocpp2.0.1, ocpp1.6), in order of preference, and the CSMS picks one. The whole connection then speaks that version. 1.6 and 2.x differ in almost every message, so a CSMS that serves both has a handler per version on the same endpoint.
The CSMS decides whether to accept the station before the WebSocket upgrade: an unknown identity gets HTTP 404, wrong credentials HTTP 401.
Messages on the wire
Section titled “Messages on the wire”Every OCPP-J message is a JSON array. A request is a CALL, and every CALL is answered by exactly one CALLRESULT or CALLERROR:
[2, "19223201", "BootNotification", {"reason": "PowerUp", "chargingStation": {"vendorName": "VendorX", "model": "SingleSocketCharger"}}][3, "19223201", {"currentTime": "2026-10-19T08:00:00Z", "interval": 300, "status": "Accepted"}][4, "19223201", "FormatViolation", "chargingStation: required", {}]| Type | Number | Versions | Meaning |
|---|---|---|---|
| CALL | 2 | all | A request, with a message id, an action and a payload |
| CALLRESULT | 3 | all | The answer to a CALL, with the same message id |
| CALLERROR | 4 | all | An error answer: NotImplemented, NotSupported, FormatViolation, SecurityError and others |
| CALLRESULTERROR | 5 | 2.1 | The receiver of a CALLRESULT says the result was wrong |
| SEND | 6 | 2.1 | A message that is never answered, for streams of data |
Each side has one outstanding CALL at a time: it waits for the answer before it sends the next request. Requests from the other side can arrive meanwhile. The action names the message (BootNotification, Heartbeat, TransactionEvent, SetChargingProfile, …), and each action is sent by one role, except DataTransfer, which both send.
A request or answer that does not match its OCA schema is answered with a CALLERROR. go-ocpp validates every message against the schemas in both directions, and ocppctl reports which field failed and why.
Versions
Section titled “Versions”| Version | Status in go-ocpp | What it brings |
|---|---|---|
| OCPP 1.6J | 39 actions: 28 core, 11 from the Security Whitepaper (Edition 4) | Still the most widely deployed. Connectors numbered across the station, configuration keys, transactions with an integer id the CSMS assigns |
| OCPP 2.0.1 | 64 actions (Edition 4, errata 2026-09) | A device model of components and variables, EVSEs with connectors, TransactionEvent with an id the station chooses, security built in, ISO 15118 support messages |
| OCPP 2.1 | 91 actions (Edition 2, errata 2026-09) | Builds on 2.0.1: bidirectional charging and DER control, tariffs and cost, battery swap, local controllers, and the SEND and CALLRESULTERROR message types |
| OCPP 1.6 SOAP, 1.5 and older | Out of scope |
2.0.1 and 2.1 are close, but not the same: their types are generated separately from each version’s schemas (ocpp201 and ocpp21), because the schemas do differ. 2.1 opened up the id token types, for example.
A charging session
Section titled “A charging session”A charging session in OCPP 2.0.1, as the station sees it:
- BootNotification: the station registers. The CSMS answers
Accepted(with the heartbeat interval),PendingorRejected. Many CSMSs refuse other messages until the boot is accepted. - StatusNotification for each connector, then Heartbeat at the interval the CSMS gave.
- A driver presents a card: Authorize with the id token.
- TransactionEvent
Started, thenUpdatedwith meter values while charging, thenEndedwith the final meter reading.
In OCPP 1.6 the session is StartTransaction, MeterValues and StopTransaction instead, and the CSMS assigns the transaction id in its answer to StartTransaction. In 2.x the station chooses a string id.
The CSMS can start the same session remotely (RequestStartTransaction, in 1.6 RemoteStartTransaction), stop it, or limit it.
Smart charging
Section titled “Smart charging”The CSMS limits power with charging profiles: a station maximum, a default for every transaction (TxDefaultProfile) or a profile for one transaction (TxProfile), each a schedule of limits in W or A. SetChargingProfile installs one, GetCompositeSchedule asks the station what it will actually do, and ClearChargingProfile removes them. Grid operators and energy management systems use this to keep a site within its connection capacity. How a station combines its profiles is charging logic, which belongs to the application: go-ocpp carries the messages, and its smart-charging example shows a simple composite schedule.
Configuration
Section titled “Configuration”A 1.6 station has configuration keys (GetConfiguration, ChangeConfiguration), such as HeartbeatInterval. A 2.x station has a device model of components and variables (GetVariables, SetVariables, GetBaseReport with NotifyReport), such as the variable HeartbeatInterval of the component OCPPCommCtrlr.
Security
Section titled “Security”OCPP defines three security profiles. In OCPP 1.6 they come from the Security Whitepaper; in 2.x they are part of the specification.
| Profile | Transport | The station proves its identity with |
|---|---|---|
| 1 | ws://, no encryption |
An HTTP Basic password. For closed networks only |
| 2 | wss://, TLS |
An HTTP Basic password; the station verifies the CSMS certificate |
| 3 | wss://, mutual TLS |
A client certificate whose CommonName is its identity |
The Basic user name is the station identity. go-ocpp and ocppctl require TLS 1.2 or later, and TLS verification cannot be turned off: a test CA is trusted explicitly instead. go-ocpp’s ocppcert package computes the CertificateHashData that DeleteCertificate and GetCertificateStatus refer to.
Not all of OCPP is security: a station that connects under the identity of another can push it off its CSMS, and remote start and stop act on real chargers and real money. Test against stations and a CSMS you own, with test identities and tokens.
Where OCPP is used in energy
Section titled “Where OCPP is used in energy”Charging stations are among the largest flexible loads on the low-voltage grid, and OCPP is how a charge point operator, an aggregator or a building’s energy management system reaches them. The same smart charging messages that cap a site at its connection limit can follow a price or a grid signal, for example one an energy management system receives over OpenADR. OCPP 2.1 adds bidirectional charging and DER control, so a car can feed power back.
OCPP is one of several protocols around a charger. ISO 15118 runs between the car and the station (Plug & Charge), OCPI between charge point operators and roaming platforms, and OSCP between grid operators and charge point operators about capacity. OT Fabric implements OCPP.
OT Fabric for OCPP
Section titled “OT Fabric for OCPP”| Project | What it is |
|---|---|
| go-ocpp | OCPP 1.6J, 2.0.1 and 2.1 for Go: a charging station client and a CSMS server on one RPC engine, every action typed and validated against the OCA schemas, security profiles 1 to 3, compression, a test kit and certificate helpers. One dependency. Pre-release, v0.1.3. |
| ocppctl | A command-line tool on go-ocpp: probe a CSMS, send any message, simulate one or hundreds of stations, run scenarios in CI, and serve a CSMS for station development. v0.1.1. |
| ocpp-interop | Docker images of five independent OCPP implementations behind one container contract, with deterministic fixtures for every action of each version. v0.4.1. |