Introduction - CSMS Developer Guide
Based on Open Charge Point Protocol 1.6, Edition 2 FINAL (2017-09-28). This guide covers the core protocol concepts, transport layer, feature profiles, authorization, smart charging, metering, and all message schemas from the CSMS perspective.
1. Overview
Section 3.0This is the specification for OCPP version 1.6. OCPP is a standard open protocol for communication between Charge Points and a Central System and is designed to accommodate any type of charging technique. OCPP 1.6 introduces new features: Smart Charging, OCPP using JSON over Websockets, better diagnostics possibilities (Reason), more Charge Point Statuses and TriggerMessage. OCPP 1.6 is based on OCPP 1.5, with some new features and a lot of textual improvements, clarifications and fixes for all known ambiguities. Due to improvements and new features, OCPP 1.6 is not backward compatible with OCPP 1.5.
New in OCPP 1.6
Smart Charging
Enables intelligent energy management and load balancing across Charge Points.
JSON over WebSocket
New transport option using JSON payloads over persistent WebSocket connections.
Better Diagnostics
Improved diagnostics capabilities including the Reason field.
More Statuses
Additional Charge Point statuses for more granular state reporting.
TriggerMessage
Allows the Central System to request the Charge Point to send a specific message.
Textual Improvements
Clarifications and fixes for all known ambiguities from OCPP 1.5.
Edition 2
Section 3.1This document is OCPP 1.6 edition 2. It describes the same protocol as the original OCPP 1.6 (October 2015) — no message-level changes were made. Edition 2 merges all known errata (including v3.0), improves documentation, and clarifies ambiguities.
Important: When there is doubt about the way OCPP 1.6 should be implemented, this document (edition 2) rules over the original.
Document Structure
Section 3.2OCPP 1.6 has two transport flavors. The base protocol document defines message semantics and payloads. It must be paired with one of the transport protocol specifications for implementation.
| Flavor | Suffix | Transport Specification |
|---|---|---|
OCPP-J | -J | OCPP JSON Specification (WebSocket + JSON) |
OCPP-S | -S | OCPP SOAP Specification |
Naming Convention: To avoid confusion in communication on the type of
implementation, it is recommended to use the distinct suffixes -J and -S to indicate JSON
or SOAP.
For improved interoperability between Central Systems and Charge Points, it is advised to meet the requirements stated in the OCPP 1.6 Compliance testing documentation.
OCPP-S vs OCPP-J Comparison
A side-by-side comparison of the two transport protocol options available in OCPP 1.6.
| Aspect | OCPP-S (SOAP) | OCPP-J (JSON) |
|---|---|---|
| Transport | HTTP(S) / SOAP | WebSocket (RFC 6455) |
| Message format | XML / SOAP envelope | JSON arrays |
| Connection model | Request/response per HTTP call | Persistent full-duplex WebSocket |
| NAT traversal | Requires intermediary smart device | CP opens TCP to CSMS; kept open for bidirectional use |
| Message overhead | High (XML + SOAP headers) | Low (compact JSON) |
2. OCPP-J Transport Layer
JSON over WebSocketThis section is normative. It describes the OCPP-J transport layer based on JSON over WebSocket, covering connection establishment, subprotocol negotiation, the RPC framework, connection management, and security. Source: OCPP-J 1.6 Implementation Guide (FINAL, 2015-10-08).
3.2a.1 Connection URL
The Charge Point derives its connection URL from the Central System's OCPP-J endpoint URL by following these steps:
1. Base Endpoint
Take the CSMS endpoint URL (e.g., ws://centralsystem.example.com/ocpp)
2. Separator
Append a / separator
3. CP Identity
Append the unique Charge Point identity string (percent-encoded per RFC 3986)
Endpoint URL: ws://centralsystem.example.com/ocpp
CP Identity: CP001
Connection URL: ws://centralsystem.example.com/ocpp/CP001
Endpoint URL: wss://centralsystem.example.com/ocppj
CP Identity: RDAM 123
Connection URL: wss://centralsystem.example.com/ocppj/RDAM%20123Requirements
- The CSMS MUST provide at least one OCPP-J endpoint URL.
- The endpoint URL can use
ws://orwss://scheme. - It is good practice to include the OCPP version in the endpoint URL path.
- Charge Point identity is NOT included in individual messages. It is established during the WebSocket handshake.
3.2a.2 Subprotocol Negotiation
The OCPP version MUST be specified in the Sec-WebSocket-Protocol header during the WebSocket handshake.
| OCPP Version | WebSocket Subprotocol Name |
|---|---|
| 1.2 | ocpp1.2 |
| 1.5 | ocpp1.5 |
| 1.6 | ocpp1.6 |
| 2.0 | ocpp2.0 |
WebSocket Handshake Example
GET /webServices/ocpp/CP3211 HTTP/1.1
Host: some.server.com:33033
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: ocpp1.6, ocpp1.5
Sec-WebSocket-Version: 13HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: ocpp1.6| Condition | Server Behavior |
|---|---|
| Unrecognized CP identity in URL path | SHOULD respond with HTTP 404 and abort the WebSocket connection |
| No acceptable subprotocol offered | MUST complete handshake without Sec-WebSocket-Protocol header, then immediately close the WebSocket connection |
3.2a.3 RPC Framework
OCPP-J defines a lightweight RPC framework on top of WebSocket, inspired by WAMP. It provides the request/response correlation that WebSocket itself lacks.
Message Types
| MessageType | MessageTypeNumber | Direction |
|---|---|---|
CALL | 2 | Client-to-Server or Server-to-Client |
CALLRESULT | 3 | Server-to-Client or Client-to-Server |
CALLERROR | 4 | Server-to-Client or Client-to-Server |
Message ID Rules
| Property | Rule |
|---|---|
| Datatype | string |
| Max length | 36 characters (to allow GUIDs/UUIDs) |
| Uniqueness (CALL) | MUST be unique across all CALL messages sent by the same sender on the same connection |
| Matching (CALLRESULT / CALLERROR) | MUST equal the message ID of the CALL it responds to |
CALL
[<MessageTypeId>, "<UniqueId>", "<Action>", {<Payload>}][2, "19223201", "BootNotification", {"chargePointVendor": "VendorX", "chargePointModel": "SingleSocketCharger"}]CALLRESULT
[<MessageTypeId>, "<UniqueId>", {<Payload>}][3, "19223201", {"status":"Accepted", "currentTime":"2013-02-01T20:53:32.486Z", "heartbeatInterval":300}]CALLERROR
[<MessageTypeId>, "<UniqueId>", "<ErrorCode>", "<ErrorDescription>", {<ErrorDetails>}]RPC Error Codes
| Error Code | Description |
|---|---|
NotImplemented | Requested Action is not known by the receiver |
NotSupported | Requested Action is recognized but not supported by the receiver |
InternalError | An internal error occurred and the receiver was not able to process the requested Action |
ProtocolError | Payload for Action is incomplete |
SecurityError | During processing, a security issue occurred preventing the Action from completing |
FormationViolation | Payload is syntactically incorrect or does not conform to the PDU structure for the Action |
PropertyConstraintViolation | Payload is syntactically correct but at least one field contains an invalid value |
OccurenceConstraintViolation | Payload is syntactically correct but at least one field violates occurrence constraints |
TypeConstraintViolation | Payload is syntactically correct but at least one field violates data type constraints |
GenericError | Any other error not covered by the above |
Important: Error situations defined in the OCPP response schema (e.g., status: "Rejected") are NOT CALLERROR-level errors. They are valid CALLRESULT payloads.
CALLERROR is reserved for transport/protocol-level failures.
Synchronicity
- A CP or CSMS SHOULD NOT send a new CALL message until all previous CALLs have been responded to or have timed out.
- A party can receive a CALL from the other side while waiting for a CALLRESULT/CALLERROR.
Character Encoding
The entire message MUST be valid JSON encoded in UTF-8.
3.2a.4 Connection Management
Compression: Do NOT use WebSocket compression extensions.
WebSocket Ping vs OCPP Heartbeat
| Feature | WebSocket Ping/Pong | OCPP Heartbeat |
|---|---|---|
| Connection liveness | Yes | Yes |
| NAT keep-alive | Yes | Yes |
| Time synchronization | No | Yes (response includes server time) |
Even when using WebSocket Ping/Pong, send at least one OCPP Heartbeat per day.
Reconnecting
When a CP reconnects after a connection drop, it SHOULD NOT send a BootNotification unless one or more fields have changed.
NAT Traversal
The CP initiates the TCP connection to the CS. This connection is kept open for bidirectional communication.
3.2a.5 Security
A CS SHOULD NOT listen for incoming unencrypted OCPP-J connections from the internet.
Two security approaches are available: Network-Level Security (VPN, private network) and OCPP-J over TLS (wss://).
TLS Certificate: The TLS certificate SHALL be RSA, no greater than 2048 bytes.
HTTP Basic Authentication
| Field | Value |
|---|---|
| Username | The Charge Point identity |
| Password | A 20-byte authorization key stored on the Charge Point |
Charge Point identity: AL1000
Authorization key: 0001020304050607FFFFFFFFFFFFFFFFFFFFFFFF
HTTP Header:
Authorization: Basic QUwxMDAwOgABAgMEBQYH/////////////////Authorization Key Rotation Flow
Charge Point Central System
| |
|--- WS Connect (HTTP GET + auth: <old key>) ----->|
|<--------------- HTTP 101 Upgrade ----------------|
| |
|--- BootNotification.req ------------------------>|
|<-- BootNotification.conf (status=Pending) -------|
| |
|<-- ChangeConfiguration.req("AuthorizationKey", |
| <new key hex>) ---------------------------|
|--- ChangeConfiguration.conf(Accepted) ---------->|
| |
|<========= Central System closes WS ==============|
| |
|--- WS Connect (HTTP GET + auth: <new key>) ----->|
|<--------------- HTTP 101 Upgrade ----------------|
| |
|--- BootNotification.req ------------------------>|
|<-- BootNotification.conf (status=Accepted) ------|3. Feature Profiles
NormativeIn OCPP 1.6 features and associated messages are grouped in profiles. Depending on the required functionality, implementers can choose to implement one or more profiles.
Profile Overview
| Profile Name | Description |
|---|---|
Core | Basic Charge Point functionality comparable with OCPP 1.5, without firmware updates, local authorization list management, or reservations. |
Firmware Management | Support for firmware update management and diagnostic log file download. |
Local Auth List Management | Features to manage the local authorization list in Charge Points. |
Reservation | Support for reservation of a Charge Point. |
Smart Charging | Support for basic Smart Charging, for instance using control pilot. |
Remote Trigger | Support for remote triggering of Charge Point initiated messages. |
Important: Implementation of the Core profile is required. Other profiles are optional.
When the profiles Core, Firmware Management, Local Auth List Management, and Reservation are all implemented, all functions originating from OCPP 1.5 are covered.
The support for specific feature profiles is reported by the SupportedFeatureProfiles configuration key.
Core Profile
| Message | Direction |
|---|---|
Authorize | CP → CS |
BootNotification | CP → CS |
ChangeAvailability | CS → CP |
ChangeConfiguration | CS → CP |
ClearCache | CS → CP |
DataTransfer | Bidirectional |
GetConfiguration | CS → CP |
Heartbeat | CP → CS |
MeterValues | CP → CS |
RemoteStartTransaction | CS → CP |
RemoteStopTransaction | CS → CP |
Reset | CS → CP |
StartTransaction | CP → CS |
StatusNotification | CP → CS |
StopTransaction | CP → CS |
UnlockConnector | CS → CP |
Firmware Management Profile
| Message | Direction |
|---|---|
GetDiagnostics | CS → CP |
DiagnosticsStatusNotification | CP → CS |
FirmwareStatusNotification | CP → CS |
UpdateFirmware | CS → CP |
Local Auth List Management Profile
| Message | Direction |
|---|---|
GetLocalListVersion | CS → CP |
SendLocalList | CS → CP |
Reservation Profile
| Message | Direction |
|---|---|
CancelReservation | CS → CP |
ReserveNow | CS → CP |
Smart Charging Profile
| Message | Direction |
|---|---|
ClearChargingProfile | CS → CP |
GetCompositeSchedule | CS → CP |
SetChargingProfile | CS → CP |
Remote Trigger Profile
| Message | Direction |
|---|---|
TriggerMessage | CS → CP |
4. General Views of Operation
InformativeThis section provides informative overviews of typical operational flows between a Charge Point and the Central System. These diagrams illustrate the expected message sequences for common operations.
Typical Transaction Flow
A typical charging transaction involves authorization, starting the transaction, optionally re-authorizing for a different user to stop, and then stopping the transaction.
Charge Point Central System
| |
| Authorize.req(idTag) |
| ─────────────────────────────────────────────────────────> |
| Authorize.conf(idTagInfo) |
| <───────────────────────────────────────────────────────── |
| |
| [Start Charging] |
| |
| StartTransaction.req(connectorId, idTag, |
| meterStart, timestamp, [reservationId]) |
| ─────────────────────────────────────────────────────────> |
| StartTransaction.conf(idTagInfo, transactionId) |
| <───────────────────────────────────────────────────────── |
| |
| [Charging...] |
| |
| Authorize.req(idTag) — to stop by different user |
| ─────────────────────────────────────────────────────────> |
| Authorize.conf(idTagInfo) |
| <───────────────────────────────────────────────────────── |
| |
| [Stop Charging] |
| |
| StopTransaction.req(meterStop, timestamp, |
| transactionId, [reason], [idTag], |
| [transactionData]) |
| ─────────────────────────────────────────────────────────> |
| StopTransaction.conf([idTagInfo]) |
| <───────────────────────────────────────────────────────── |Key Rules
- • A Charge Point authenticates the user first
(
Authorize.req), then informs the Central System that charging has started (StartTransaction.req). - • To stop, the CP verifies the user is the same who started, or is in the same group
(
parentIdTag), and is thus allowed to stop. - • A Charge Point MUST NOT send an
Authorize.reqbefore stopping a transaction if the presentedidTagis the same as theidTagpresented to start the transaction.
Typical Firmware Update Flow
Firmware updates are initiated by the Central System. The Charge Point downloads, installs, and reboots, notifying the Central System at each step.
Central System Charge Point
| |
| UpdateFirmware.req(location, retrieveDate, |
| [retries], [retryInterval]) |
| ─────────────────────────────────────────────────────────> |
| UpdateFirmware.conf() |
| <───────────────────────────────────────────────────────── |
| |
| [Downloading firmware...] |
| |
| FirmwareStatusNotification.req(status: Downloaded) |
| <───────────────────────────────────────────────────────── |
| FirmwareStatusNotification.conf() |
| ─────────────────────────────────────────────────────────> |
| |
| [Installing firmware...] |
| |
| FirmwareStatusNotification.req(status: Installed) |
| <───────────────────────────────────────────────────────── |
| FirmwareStatusNotification.conf() |
| ─────────────────────────────────────────────────────────> |
| |
| [Reboot] |
| |
| BootNotification.req(...) |
| <───────────────────────────────────────────────────────── |
| BootNotification.conf(currentTime, |
| heartbeatInterval, status) |
| ─────────────────────────────────────────────────────────> |Note: The Charge Point SHALL notify the Central System after each step as it downloads and installs the new firmware.
6. Transactions
Normative3.6 Transaction in Relation to Energy Transfer Period
InformativeThis subsection is informative. It describes the relationship between the overarching Charging Session, the Transaction, Energy Offer Periods, and Energy Transfer Periods. A transaction encompasses the full lifecycle from when all preconditions are met until the Charge Point irrevocably leaves that state.
┌───────────────────────────────────────────────────────────┐
│ Charging Session │
│ (First interaction with user/EV → station available) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Transaction │ │
│ │ (All preconditions met → irrevocably leaves state) │ │
│ │ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Energy Offer Period │ │ │
│ │ │ (EVSE ready and willing) │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────────────┐ │ │ │
│ │ │ │ Energy Transfer Period │ │ │ │
│ │ │ │ (Actual energy flow) │ │ │ │
│ │ │ └────────────────────────┘ │ │ │
│ │ └──────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Energy Offer Suspend Period │ │ │
│ │ │ (Smart Charging / local balance)│ │ │
│ │ └──────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Energy Offer Period │ │ │
│ │ │ ┌────────────────────────┐ │ │ │
│ │ │ │ Energy Transfer Period │ │ │ │
│ │ │ └────────────────────────┘ │ │ │
│ │ └──────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘Key Points
- • There MAY be multiple Energy Transfer Periods during a single Transaction.
- • Suspensions can be EVSE-initiated or EV-initiated.
- • The Central System MAY deduce the start/end of an Energy Transfer Period
from
StatusNotificationmessages:Charging,SuspendedEV,SuspendedEVSE. - • Some EVs don't go to
SuspendedEVstate — they might trickle charge instead. - • Some Charge Points don't have an electrical meter.
3.7 Transaction-Related Messages
NormativeTransaction-related messages are those directly associated with a charging transaction. They require special handling, especially regarding delivery order and offline queuing.
Transaction-Related Messages
- •
StartTransaction.req - •
StopTransaction.req - • Periodic or clock-aligned
MeterValues.reqmessages
Delivery Rules
- 1 The Charge Point SHOULD deliver transaction-related messages in chronological order as soon as possible.
- 2 When offline, the Charge Point MUST queue transaction-related messages that it would have sent if online.
- 3 Non-transaction-related messages MAY be delivered immediately without waiting for the queue to empty — they skip ahead.
- 4 New transaction-related messages SHALL wait until the queue has been emptied.
- 5 The Central System should process historical queued messages the same as any other.
3.7.1 Error Responses
It is permissible for the Charge Point to skip a transaction-related message if the Central System repeatedly reports a failure to process it. The retry behavior is governed by two configuration keys.
Retry Behavior Configuration Keys
| Configuration Key | Description |
|---|---|
TransactionMessageAttempts | Number of retry attempts for failed transaction-related messages. |
TransactionMessageRetryInterval | Base interval (seconds) between retries. Actual wait = interval × number of preceding transmissions. |
Example: TransactionMessageAttempts=3, TransactionMessageRetryInterval=60
- 1 First failure → wait 60s → retry
- 2 Second failure → wait 120s → retry
- 3 Third failure → discard message, continue with next
7. Identifiers & Connectors
NormativeThis section covers the rules for connector numbering, identity token handling, and group-based authorization using parent identity tags.
3.8 Connector Numbering
ConnectorIds MUST be numbered consistently across the Charge Point.
| Rule | Description |
|---|---|
| First connector ID | MUST be 1 |
| Sequential numbering | MUST be sequential (no skipping numbers) |
| Upper bound | MUST never be higher than the total number of connectors |
| ConnectorId 0 (CS→CP) | Reserved for addressing the entire Charge Point |
| ConnectorId 0 (CP→CS) | Reserved for the Charge Point main controller |
Example
A Charge Point with 3 connectors → Connector IDs: 1, 2, 3.
Developer Notes
ConnectorId 0 is
special and used in different contexts:
-
StatusNotificationwithConnectorId=0reports errors/status for the Charge Point itself (not a specific connector). -
ChargePointMaxProfile(smart charging) can only be set atConnectorId=0. - Operations initiated by the CS with
ConnectorId=0address the entire CP (e.g.,ChangeAvailabilitywith connector 0 changes availability of all connectors).
3.9 ID Tokens
IdToken data is usually a 4 or 7 byte UID value of a physical RFID card, typically represented as 8/14 hexadecimal digit characters.
Remote Sessions
IdTokens sent by Central Systems for remotely initiated charging sessions may commonly be (single use) virtual transaction authorization codes.
Parent IDs
IdToken data used as ParentIds may often use a shared central account identifier.
Rules
| Rule | Description |
|---|---|
| Content flexibility | IdToken data (including ParentId) MAY contain any data subject to CiString20Type constraints. |
| No format assumptions | Charge Points MUST NOT make any presumptions about format or content. |
| RFID interoperability | For interoperability with ISO 14443 compatible RFID card UIDs, it is RECOMMENDED that such UIDs be represented as hex representations of the UID bytes. According to ISO14443-3, byte 0 should come first in the hex string. |
3.10 Parent idTag
A Central System can treat a set of identity tokens as a "group", allowing any token in the group to start a transaction and any other token in the group to stop it.
Use Case: Families
Multiple family members sharing one recharging contract account, each with their own RFID card.
Use Case: Businesses
Multiple drivers within a business sharing a single corporate recharging contract account.
Implementation
- Tokens are grouped by specifying a common group identifier in the optional
parentIdTagelement inIdTagInfo. - Two idTags are in the same group if their
parentIdTagvalues match. - The
parentIdTagvalue has the same data type (IdToken / CiString20Type) as an idTag, but it may not represent an actual valid IdToken. - The
parentIdTagvalue SHOULD NOT be used for comparison against a presented Token value.
8. Reservations & Data Transfer
Informative3.11 Reservations
Reservation is possible using the ReserveNow operation:
- • Reserves a Charge Point until a certain expiry time for a specific
idTag. - • A
parentIdTagmay be included for "group" reservations. - • Can reserve a specific connector
(
connectorId > 0) or any connector (connectorId = 0). - • A reservation is released when:
- – The reserved
idTagis used on the reserved connector. - – The expiry time is reached.
- – The reservation is explicitly canceled
(
CancelReservation).
- – The reserved
{
"connectorId": integer, // REQUIRED — 0 = any connector
"expiryDate": "date-time", // REQUIRED
"idTag": "string (max 20)", // REQUIRED
"parentIdTag": "string (max 20)", // optional — for group reservations
"reservationId": integer // REQUIRED
}{
"status": "Accepted" | "Faulted" | "Occupied" | "Rejected" | "Unavailable"
}{
"reservationId": integer
}{
"status": "Accepted" | "Rejected"
}3.12 Vendor-Specific Data Transfer
The DataTransfer mechanism allows exchange of data or messages not standardized in OCPP. Two main uses:
1. Experimental Functionality
Experimental functionality that may find its way into future OCPP versions.
2. Additional Functionality
Additional functionality agreed upon between specific Central System and Charge Point vendors.
The operation MAY be initiated either by the Central System or by the Charge Point.
Warning: Please use with extreme caution and only for optional functionality, since it will impact your compatibility with other systems that do not make use of this option. Please consider consulting the Open Charge Alliance before turning to this option.
{
"vendorId": "string (max 255)", // REQUIRED — identifies the vendor
"messageId": "string (max 50)", // optional — identifies the message type
"data": "string" // optional — payload data
}{
"status": "Accepted" | "Rejected" | "UnknownMessageId" | "UnknownVendorId",
"data": "string" // optional — response payload
}9. Smart Charging
NormativeWith Smart Charging a Central System gains the ability to influence the charging power or current of a specific EV, or the total allowed energy consumption on an entire Charge Point / a group of Charge Points.
3.13.1 Charging Profile Purposes
Section 3.13.1Three types of charging profile purposes are defined:
ChargePointMaxProfile
- • In load balancing scenarios, limits the power or current shared by all connectors of a Charge Point.
- • Can only be set at
ConnectorId 0.
TxDefaultProfile
- • Default schedules for new transactions.
- • If set at
ConnectorId 0: applies to all connectors. - • If set at
ConnectorId > 0: applies only to that specific connector.
TxProfile
- • Transaction-specific profile that overrules
TxDefaultProfile. - • Can only be set at
ConnectorId > 0. - • After the transaction is stopped, the profile SHOULD be deleted.
- • If there is no transaction active, the CP SHALL discard it and return an error.
3.13.2 Stacking Charging Profiles
Section 3.13.2It is allowed to stack charging profiles of the same purpose to describe complex calendars.
Precedence Rules
Determined by the stackLevel parameter — higher stackLevel = higher priority.
At any point in time, the prevailing profile SHALL be the one with
the highest stackLevel.
Multiple profiles with the same stackLevel AND Purpose on a CP are not allowed — if received, the CP SHALL replace the existing profile.
Important: If an updated profile is sent with a future validFrom,
the CP SHALL replace the installed profile and revert to default
behavior until validFrom is reached.
Caution: If you use stacking without a duration on the highest stack level, the CP will never fall back to a lower stack level
profile.
3.13.3 Combining Charging Profile Purposes
Section 3.13.3The Composite Schedule is calculated by taking the minimum value for each time interval
across all profile purposes. When the CP has more than one Connector, the ChargePointMaxProfile limit applies to all connectors combined.
3.13.4 Smart Charging Use Cases
Section 3.13.4Three use cases are defined for Smart Charging:
Load Balancing
- • Internal load balancing within the CP.
- • CP controls the charging schedule per connector.
- • CP is configured with a fixed limit.
- • Optional
minChargingRatefield optimizes power distribution.
Central Smart Charging
- • Charge limits controlled by the Central System per transaction.
- • CS receives capacity forecasts and calculates per-transaction schedules.
- • CS imposes limits via
SetChargingProfile.reqwithTxProfilepurpose.
Local Smart Charging
- • Controlled locally by a Local Controller.
- • The Local Controller implements OCPP and acts as a proxy for group members.
- • Uses
SetChargingProfile.reqwithChargePointMaxProfilepurpose onConnectorId 0.
3.13.5 Discovery
The following configuration keys are used to discover the Smart Charging capabilities of a Charge Point:
| Configuration Key | Type | Description |
|---|---|---|
ChargeProfileMaxStackLevel | integer | Max number of stack levels the CP supports. |
ChargingScheduleAllowedChargingRateUnit | CSL | Supported charging rate units: Current and/or Power. |
ChargingScheduleMaxPeriods | integer | Max number of periods in a ChargingSchedule. |
MaxChargingProfilesInstalled | integer | Max number of charging profiles that can be installed. |
3.13.6 Offline Behavior
Section 3.13.6If a CP goes offline after receiving a TxProfile,
it SHALL continue to use it.
If a CP goes offline before receiving a TxProfile,
it SHALL use available ChargePointMaxProfile and TxDefaultProfile.
If a CP goes offline without any charging profiles, it SHALL execute a transaction as if no constraints apply.
3.13.7 Example Data Structure
InformativeThe following example shows a recurring daily charging profile with three periods:
| Field | Value |
|---|---|
chargingProfileId | 100 |
stackLevel | 0 |
chargingProfilePurpose | TxDefaultProfile |
chargingProfileKind | Recurring |
recurrencyKind | Daily |
duration | 86400 (= 24 hours) |
startSchedule | 2013-01-01T00:00:00Z |
chargingRateUnit | W |
Charging Schedule Periods
| Period | startPeriod | limit | numberPhases |
|---|---|---|---|
| Period 1 | 0 (=00:00) | 11000 | 3 |
| Period 2 | 28800 (=08:00) | 6000 | 3 |
| Period 3 | 72000 (=20:00) | 11000 | 3 |
Notes
Phase Limitations
The amount of phases used during charging is limited by the capabilities of: the Charge Point, the EV, and the Cable.
Phase Switching Caution: Some EVs may not support switching phases
during a session. See configuration key ConnectorSwitch3to1PhaseSupported.
DST Note: On days where DST goes into or out of effect, a special profile might be needed to account for the time shift.
10. Time & Metering
Normative3.14 Time Zones
OCPP does not prescribe a specific time zone. It is strongly recommended to use UTC for all time values.
Recommendation: Always use UTC for all time values exchanged between the Central System and Charge Point.
3.15 Time Notations
Implementations MUST use ISO 8601 date time notation. Message receivers must be able to handle fractional seconds and time zone offsets.
3.16 Metering Data
Two obvious use cases for extensive metering data:
- • Charging Session Meter Values
- • Clock-Aligned Meter Values
Both MAY be reported in standalone MeterValues.req messages and/or as part of StopTransaction.req.
{
"timestamp": "2024-01-15T10:30:00Z",
"sampledValue": [
{
"value": "1234.5",
"context": "...",
"format": "...",
"measurand": "...",
"phase": "...",
"location": "...",
"unit": "..."
}
]
}SampledValue Fields
| Field | Values | Default | Description |
|---|---|---|---|
value | string | — | REQUIRED. The measured value. |
context | Interruption.Begin, Interruption.End, Sample.Clock, Sample.Periodic, Transaction.Begin, Transaction.End, Trigger, Other | Sample.Periodic | Why the value was sampled. |
format | Raw, SignedData | Raw | Format. SignedData = cryptographically signed. |
measurand | See measurands table | Energy.Active.Import.Register | What was measured. |
phase | L1, L2, L3, N, L1-N, L2-N, L3-N, L1-L2, L2-L3, L3-L1 | (absent = overall) | Which phase. |
location | Cable, EV, Inlet, Outlet, Body | Outlet | Where measured. |
unit | Wh, kWh, varh, kvarh, W, kW, VA, kVA, var, kvar, A, V, K, Celcius, Celsius, Fahrenheit, Percent | Wh | Unit. |
Measurand Values
| Measurand | Description |
|---|---|
Energy.Active.Export.Register | Total exported active energy (Wh). |
Energy.Active.Import.Register | Total imported active energy (Wh). Default measurand. |
Energy.Reactive.Export.Register | Total exported reactive energy (varh). |
Energy.Reactive.Import.Register | Total imported reactive energy (varh). |
Energy.Active.Export.Interval | Active energy exported during last interval. |
Energy.Active.Import.Interval | Active energy imported during last interval. |
Energy.Reactive.Export.Interval | Reactive energy exported during last interval. |
Energy.Reactive.Import.Interval | Reactive energy imported during last interval. |
Power.Active.Export | Instantaneous active power exported (W). |
Power.Active.Import | Instantaneous active power imported (W). |
Power.Offered | Maximum power offered to EV (W). |
Power.Reactive.Export | Instantaneous reactive power exported (var). |
Power.Reactive.Import | Instantaneous reactive power imported (var). |
Power.Factor | Power factor (dimensionless, -1..1). |
Current.Import | Instantaneous current imported (A). |
Current.Export | Instantaneous current exported (A). |
Current.Offered | Maximum current offered to EV (A). |
Voltage | Instantaneous voltage (V). |
Frequency | Power supply frequency (Hz). |
Temperature | Temperature reading. |
SoC | State of Charge (%). |
RPM | Fan speed (RPM). |
3.16.1 Charging Session Meter Values
Frequent (e.g. 1-5 minute interval) meter readings. Controlled by the following configuration keys:
MeterValuesSampledData — list of measurands to include in periodic meter value messages.
MeterValuesSampledDataMaxLength — maximum number of items in the sampled data list.
MeterValueSampleInterval — interval (seconds) between meter value samples (0 = disabled).
StopTxnSampledData — measurands to include in StopTransaction.req.
StopTxnSampledDataMaxLength — maximum number of items in stop transaction sampled data.
3.16.2 Clock-Aligned Meter Values
Grid Operator may require meter readings at specific clock-aligned times. Controlled by the following configuration keys:
ClockAlignedDataInterval — interval (seconds) for clock-aligned readings (e.g. 900 = 15 minutes, yielding 96
intervals per day; 0 = disabled).
MeterValuesAlignedData — list of measurands to include in clock-aligned meter value messages.
MeterValuesAlignedDataMaxLength — maximum number of items in aligned data list.
StopTxnAlignedData — measurands to include in StopTransaction.req for aligned data.
StopTxnAlignedDataMaxLength — maximum number of items in stop transaction aligned data.
3.16.3 Multiple Locations/Phases
When the Charge Point can measure the same measurand on multiple locations or phases, all possible locations and/or phases SHALL be reported.
3.16.4 Unsupported Measurands
If a ChangeConfiguration.req contains measurands not supported by the Charge Point, the CP SHALL respond with
status = Rejected. No changes SHALL be made.
Important: The entire ChangeConfiguration.req is rejected if any measurand in the list is unsupported. No partial updates are applied.
3.16.5 No Metering Data in Stop Transaction
When StopTxnAlignedData and StopTxnSampledData are set to an empty string, the Charge Point SHALL NOT put meter values in StopTransaction.req.
Note: Setting both StopTxnAlignedData and StopTxnSampledData to empty strings effectively disables all metering data in stop transaction messages.
11. Message Schemas
Quick ReferenceThis section provides the complete JSON schemas for all OCPP 1.6 messages, organized by
feature profile. Each message is shown as a request/confirmation pair. Fields marked with REQUIRED are mandatory;
all other fields are optional.
Core Messages
Authorize
{
"idTag": "string (max 20)" // REQUIRED
}{
"idTagInfo": {
"status": "Accepted" | "Blocked" | "Expired" | "Invalid" | "ConcurrentTx",
"expiryDate": "date-time",
"parentIdTag": "string (max 20)"
}
}BootNotification
{
"chargePointVendor": "string (max 20)",
"chargePointModel": "string (max 20)",
"chargePointSerialNumber": "string (max 25)",
"chargeBoxSerialNumber": "string (max 25)",
"firmwareVersion": "string (max 50)",
"iccid": "string (max 20)",
"imsi": "string (max 20)",
"meterType": "string (max 25)",
"meterSerialNumber": "string (max 25)"
}{
"status": "Accepted" | "Pending" | "Rejected",
"currentTime": "date-time",
"interval": integer
}Heartbeat
{}{
"currentTime": "date-time"
}StartTransaction
{
"connectorId": integer,
"idTag": "string (max 20)",
"meterStart": integer,
"timestamp": "date-time",
"reservationId": integer
}{
"idTagInfo": {
"status": "Accepted" | "Blocked" | "Expired" | "Invalid" | "ConcurrentTx",
"expiryDate": "date-time",
"parentIdTag": "string (max 20)"
},
"transactionId": integer
}StopTransaction
{
"transactionId": integer,
"timestamp": "date-time",
"meterStop": integer,
"idTag": "string (max 20)",
"reason": "EmergencyStop" | "EVDisconnected" | "HardReset" | "Local" | "Other" | "PowerLoss" | "Reboot" | "Remote" | "SoftReset" | "UnlockCommand" | "DeAuthorized",
"transactionData": [MeterValue]
}{
"idTagInfo": { ... }
}StatusNotification
{
"connectorId": integer,
"errorCode": "ConnectorLockFailure" | "EVCommunicationError" | "GroundFailure" | "HighTemperature" | "InternalError" | "LocalListConflict" | "NoError" | "OtherError" | "OverCurrentFailure" | "PowerMeterFailure" | "PowerSwitchFailure" | "ReaderFailure" | "ResetFailure" | "UnderVoltage" | "OverVoltage" | "WeakSignal",
"status": "Available" | "Preparing" | "Charging" | "SuspendedEVSE" | "SuspendedEV" | "Finishing" | "Reserved" | "Unavailable" | "Faulted",
"info": "string (max 50)",
"timestamp": "date-time",
"vendorId": "string (max 255)",
"vendorErrorCode": "string (max 50)"
}{}MeterValues
{
"connectorId": integer,
"transactionId": integer,
"meterValue": [MeterValue]
}{}ChangeAvailability
{
"connectorId": integer,
"type": "Inoperative" | "Operative"
}{
"status": "Accepted" | "Rejected" | "Scheduled"
}ChangeConfiguration
{
"key": "string (max 50)",
"value": "string (max 500)"
}{
"status": "Accepted" | "Rejected" | "RebootRequired" | "NotSupported"
}ClearCache
{}{
"status": "Accepted" | "Rejected"
}GetConfiguration
{
"key": ["string (max 50)"]
}{
"configurationKey": [
{ "key": "string", "readonly": boolean, "value": "string" }
],
"unknownKey": ["string"]
}RemoteStartTransaction
{
"connectorId": integer,
"idTag": "string (max 20)",
"chargingProfile": { ... }
}{
"status": "Accepted" | "Rejected"
}RemoteStopTransaction
{
"transactionId": integer
}{
"status": "Accepted" | "Rejected"
}Reset
{
"type": "Hard" | "Soft"
}{
"status": "Accepted" | "Rejected"
}UnlockConnector
{
"connectorId": integer
}{
"status": "Unlocked" | "UnlockFailed" | "NotSupported"
}DataTransfer
{
"vendorId": "string (max 255)",
"messageId": "string (max 50)",
"data": "string"
}{
"status": "Accepted" | "Rejected" | "UnknownMessageId" | "UnknownVendorId",
"data": "string"
}Firmware Management
GetDiagnostics
{
"location": "uri-string",
"retries": integer,
"retryInterval": integer,
"startTime": "date-time",
"stopTime": "date-time"
}{
"fileName": "string (max 255)"
}DiagnosticsStatusNotification
{
"status": "Idle" | "Uploaded" | "UploadFailed" | "Uploading"
}{}FirmwareStatusNotification
{
"status": "Downloaded" | "DownloadFailed" | "Downloading" | "Idle" | "InstallationFailed" | "Installing" | "Installed"
}{}UpdateFirmware
{
"location": "uri-string",
"retrieveDate": "date-time",
"retries": integer,
"retryInterval": integer
}{}Local Auth List Management
GetLocalListVersion
{}{
"listVersion": integer
}SendLocalList
{
"listVersion": integer,
"updateType": "Differential" | "Full",
"localAuthorizationList": [
{ "idTag": "string", "idTagInfo": { ... } }
]
}{
"status": "Accepted" | "Failed" | "NotSupported" | "VersionMismatch"
}Remote Trigger
TriggerMessage
{
"requestedMessage": "BootNotification" | "DiagnosticsStatusNotification" | "FirmwareStatusNotification" | "Heartbeat" | "MeterValues" | "StatusNotification",
"connectorId": integer
}{
"status": "Accepted" | "Rejected" | "NotImplemented"
}Smart Charging
SetChargingProfile
{
"connectorId": integer,
"csChargingProfiles": {
"chargingProfileId": integer,
"transactionId": integer,
"stackLevel": integer,
"chargingProfilePurpose": "ChargePointMaxProfile" | "TxDefaultProfile" | "TxProfile",
"chargingProfileKind": "Absolute" | "Recurring" | "Relative",
"recurrencyKind": "Daily" | "Weekly",
"validFrom": "date-time",
"validTo": "date-time",
"chargingSchedule": {
"duration": integer,
"startSchedule": "date-time",
"chargingRateUnit": "A" | "W",
"chargingSchedulePeriod": [
{ "startPeriod": integer, "limit": number, "numberPhases": integer }
],
"minChargingRate": number
}
}
}{
"status": "Accepted" | "Rejected" | "NotSupported"
}ClearChargingProfile
{
"id": integer,
"connectorId": integer,
"chargingProfilePurpose": "ChargePointMaxProfile" | "TxDefaultProfile" | "TxProfile",
"stackLevel": integer
}{
"status": "Accepted" | "Unknown"
}GetCompositeSchedule
{
"connectorId": integer,
"duration": integer,
"chargingRateUnit": "A" | "W"
}{
"status": "Accepted" | "Rejected",
"connectorId": integer,
"scheduleStart": "date-time",
"chargingSchedule": { ... }
}12. Reference
AppendixConnector Status State Machine
The following diagram illustrates the state transitions of a connector. A connector begins in
the Available state and transitions through Preparing, Charging, and Finishing during a normal transaction lifecycle. Charging may be suspended by either the EVSE or the EV.
┌──────────┐
┌─────────│ Available│◄──────────────────┐
│ └─────┬────┘ │
│ │ (EV connects / │
│ │ user authenticates) │
│ ▼ │
│ ┌──────────┐ │
│ │Preparing │ │
│ └─────┬────┘ │
│ │ (all preconditions │
│ │ met, power offered) │
│ ▼ │
│ ┌──────────┐ │
│ ┌───►│ Charging │◄───┐ │
│ │ └────┬─┬───┘ │ │
│ │ │ │ │ │
│ │ ┌────┘ └────┐ │ │
│ │ ▼ ▼ │ │
│ │ ┌───────────┐ ┌───────────┐ │
│ │ │Suspended │ │Suspended │ │
│ └─┤ EVSE │ │ EV ├───┘ │
│ └───────────┘ └───────────┘ │
│ │ │
│ │ (transaction ends) │
│ ▼ │
│ ┌──────────┐ │
│ │Finishing │───────────────────┘
│ └──────────┘
│
│ ┌──────────┐
├────────►│ Reserved │ (via ReserveNow)
│ └──────────┘
│
│ ┌────────────┐
├────────►│Unavailable │ (via ChangeAvailability)
│ └────────────┘
│
│ ┌──────────┐
└────────►│ Faulted │ (hardware/software error)
└──────────┘Important: The Reserved, Unavailable, and Faulted states can be entered from Available at any time via their respective triggers.
All Configuration Keys
Comprehensive list of configuration keys used across all OCPP 1.6 feature profiles. These
keys are read and written via GetConfiguration and ChangeConfiguration.
| Key | Type | Profile | Description |
|---|---|---|---|
AllowOfflineTxForUnknownId | boolean | Core | Allow unknown identifiers when offline. |
AuthorizationCacheEnabled | boolean | Core | Enable/disable the Authorization Cache. |
AuthorizationKey | string | Core | 20-byte authentication key (40 hex chars). Write-only. |
ChargeProfileMaxStackLevel | integer | Smart Charging | Max number of stack levels. |
ChargingScheduleAllowedChargingRateUnit | CSL | Smart Charging | Supported rate units: Current and/or Power. |
ChargingScheduleMaxPeriods | integer | Smart Charging | Max periods per ChargingSchedule. |
ClockAlignedDataInterval | integer | Core | Clock-aligned sampling interval (seconds). 0=disabled. |
ConnectorSwitch3to1PhaseSupported | boolean | Smart Charging | Whether CP supports switching phases during transaction. |
LocalAuthListEnabled | boolean | Local Auth List Mgmt | Enable/disable Local Authorization List. |
LocalAuthListMaxLength | integer | Local Auth List Mgmt | Max entries in Local Authorization List. |
LocalAuthorizeOffline | boolean | Core | Use cache/list for authorization when offline. |
LocalPreAuthorize | boolean | Core | Use cache/list to start tx without waiting for CS response. |
MaxChargingProfilesInstalled | integer | Smart Charging | Max number of installed charging profiles. |
MaxEnergyOnInvalidId | integer | Core | Max energy (Wh) to deliver on invalid id. |
MeterValueSampleInterval | integer | Core | Periodic sampling interval (seconds). 0=disabled. |
MeterValuesAlignedData | CSL | Core | Measurands for clock-aligned sampling. |
MeterValuesSampledData | CSL | Core | Measurands for periodic sampling. |
StopTransactionOnInvalidId | boolean | Core | Stop tx when id is found invalid after offline auth. |
StopTxnAlignedData | CSL | Core | Measurands for aligned data in StopTransaction. |
StopTxnSampledData | CSL | Core | Measurands for sampled data in StopTransaction. |
SupportedFeatureProfiles | CSL | Core | Comma-separated list of supported profile names. |
TransactionMessageAttempts | integer | Core | Retry attempts for failed transaction messages. |
TransactionMessageRetryInterval | integer | Core | Base retry interval (seconds). |
WebSocketPingInterval | integer | Core | Interval (seconds) for WebSocket Ping frames. 0=disabled. |
Developer Implementation Checklist
Use this checklist when implementing a CSMS (Central System / Management System) that communicates with Charge Points over OCPP 1.6-J.
OCPP-J WebSocket Connection (CSMS)
- Use RFC 6455 compliant WebSocket implementation
- Accept connection URLs in the format endpoint/charge_point_id
- Respond with Sec-WebSocket-Protocol: ocpp1.6
- Return HTTP 404 for unrecognized CP identity
- If no acceptable subprotocol, complete handshake without header then immediately close
- Do NOT use WebSocket compression extensions
OCPP-J RPC Message Handling (CSMS)
- Parse incoming messages as JSON arrays; check MessageTypeId first
- Implement CALL (type 2), CALLRESULT (type 3), and CALLERROR (type 4)
- Generate unique message IDs (max 36 chars, UUIDs recommended)
- Match incoming CALLRESULT/CALLERROR to pending CALLs by message ID
- Implement timeout for unanswered CALLs
- Handle receiving a CALL while waiting for a CALLRESULT
- Ignore messages with unknown MessageTypeNumbers
- Use {} instead of null for empty payloads
- Ensure all messages are valid UTF-8 JSON
- Respond with CALLERROR for unknown/malformed actions
- Do NOT use CALLERROR for application-level rejections
- Always include all 5 fields in CALLERROR
OCPP-J Security (CSMS)
- Use wss:// (TLS) for connections over the internet
- Use RSA certificates no larger than 2048 bytes
- Implement HTTP Basic Authentication
- Never expose AuthorizationKey via GetConfiguration
- Support ChangeConfiguration for AuthorizationKey
- Implement WebSocket Ping/Pong
Central System — Must Handle
- Accept and respond to all Core profile messages
- Assign unique transactionId in StartTransaction.conf
- Return correct IdTagInfo with status, optional expiryDate and parentIdTag
- Return currentTime in BootNotification.conf and Heartbeat.conf
- Process queued offline transaction messages
- Handle StatusNotification with ConnectorId=0
- Track connector status state transitions
- Store and process MeterValues data
- Support parentIdTag-based grouping
Central System — Optional
- Send Local Authorization List updates via SendLocalList
- Manage reservations via ReserveNow / CancelReservation
- Manage firmware updates via UpdateFirmware
- Set and clear Charging Profiles for Smart Charging
- Query Composite Schedules via GetCompositeSchedule
- Use TriggerMessage for Remote Trigger profile
External References
Standards and specifications referenced throughout the OCPP 1.6 documentation.
| Reference | Description |
|---|---|
RFC 6455 | WebSocket Protocol |
RFC 5246 | TLS 1.2 |
RFC 2617 | HTTP Basic Auth |
RFC 3629 | UTF-8 |
RFC 3986 | URI Syntax |
JSON specification | json.org |
WAMP protocol | wamp.ws |