OCPP 1.6 Edition 2

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.

12 Sections
6 Feature Profiles
30+ Message Schemas

1. Overview

Section 3.0

This 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.1

This 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.2

OCPP 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 WebSocket

This 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)

Connection URL Examples
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%20123

Requirements

  • The CSMS MUST provide at least one OCPP-J endpoint URL.
  • The endpoint URL can use ws:// or wss:// 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

Client Request
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: 13
Server Response
HTTP/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

CALL Structure
[<MessageTypeId>, "<UniqueId>", "<Action>", {<Payload>}]
BootNotification CALL Example
[2, "19223201", "BootNotification", {"chargePointVendor": "VendorX", "chargePointModel": "SingleSocketCharger"}]

CALLRESULT

CALLRESULT Structure
[<MessageTypeId>, "<UniqueId>", {<Payload>}]
BootNotification CALLRESULT Example
[3, "19223201", {"status":"Accepted", "currentTime":"2013-02-01T20:53:32.486Z", "heartbeatInterval":300}]

CALLERROR

CALLERROR Structure
[<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
HTTP Basic Auth Example
Charge Point identity: AL1000
Authorization key:     0001020304050607FFFFFFFFFFFFFFFFFFFFFFFF

HTTP Header:
Authorization: Basic QUwxMDAwOgABAgMEBQYH/////////////////

Authorization Key Rotation Flow

Key Rotation Sequence
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

Normative

In 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

Informative

This 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.

Typical Transaction Flow
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.req before stopping a transaction if the presented idTag is the same as the idTag presented 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.

Typical Firmware Update Flow
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.

5. Local Authorization & Offline Behavior

Normative

In the event of unavailability of the communications or even of the Central System, the Charge Point is designed to operate stand-alone. In that situation, the Charge Point is said to be offline.

To improve the experience for users, a CP MAY support local authorization of identifiers, using an Authorization Cache and/or a Local Authorization List.

Two Local Authorization Mechanisms

Mechanism Description Configuration Key
Authorization Cache Autonomously maintained record of previously authorized identifiers. Updated from Authorize.conf, StartTransaction.conf, StopTransaction.conf responses. AuthorizationCacheEnabled
Local Authorization List A list synchronized with the Central System (full or differential updates). Contains authorization status and expiration date. LocalAuthListEnabled

Key configuration keys: LocalAuthorizeOffline and LocalPreAuthorize control whether the CP uses local authorization when offline and whether it pre-authorizes identifiers locally before contacting the Central System.

3.5.1 Authorization Cache

Section 3.5.1

A CP MAY implement an Authorization Cache that autonomously maintains a record of previously presented identifiers. The following rules apply:

The Cache contains all the latest received identifiers (valid and NOT-valid).

Updated from all received IdTagInfo (from Authorize.conf, StartTransaction.conf, StopTransaction.conf).

When a Cache entry expires, its status SHALL be changed to Expired.

When new IdTagInfo is received for an identifier already in the Cache, it SHALL be updated.

If the Cache is full, remove NOT-valid entries first, then oldest valid entries.

Cache values SHOULD be stored in non-volatile memory.

When an identifier stored as NOT-valid is presented and the CP is online: an Authorize.req SHOULD be sent.

3.5.2 Local Authorization List

Section 3.5.2

Synchronized with the Central System. Contains authorization status of all (or a selection of) identifiers. Identifiers can be marked as:

Accepted (valid) ConcurrentTx (valid) Expired Blocked (temporarily) Invalid (blacklisted)

Synchronized via two methods:

1. Full Update

SendLocalList.req with updateType: Full — replaces the entire list.

2. Differential Update

First GetLocalListVersion.req to get the current version, then SendLocalList.req with updateType: Differential.

Important: The CP SHALL NOT modify the Authorization List by any other means than via a SendLocalList PDU.

Conflict Handling

If a conflict occurs between the local authorization list and a StartTransaction.conf response, the CP SHALL inform the CS by sending a StatusNotification with ConnectorId=0 and ErrorCode=LocalListConflict.

3.5.3 Cache vs Local Authorization List

Section 3.5.3

Authorization Cache and Local Authorization List are distinct logical data structures.

Identifiers known in the Local Authorization List SHALL NOT be added to the Authorization Cache.

Priority: Where both are supported, Local Authorization List entries take priority over Authorization Cache entries.

3.5.4 Unknown Offline Authorization

Section 3.5.4

When offline, a CP MAY allow automatic authorization of any "unknown" identifier not in the Local Authorization List or Authorization Cache.

Identifiers in Local Authorization List with status other than Accepted (Invalid, Blocked, Expired) MUST be rejected.

Identifiers that were valid but have apparently expired MUST also be rejected.

Controlled by the AllowOfflineTxForUnknownId configuration key.

Offline Transaction Recovery

Section 3.5

When connection is restored, the CP SHALL send a StartTransaction request for any transaction authorized offline.

When StartTransaction.conf is not Accepted and the transaction is still ongoing:

Condition Behavior
StopTransactionOnInvalidId = true Stop the transaction normally. Set reason to DeAuthorized.
StopTransactionOnInvalidId = false Only stop energy delivery to the vehicle.

Note: An operator MAY choose to charge the EV with a minimum amount of energy so the EV can drive away. This is controlled by the MaxEnergyOnInvalidId configuration key.

6. Transactions

Normative

3.6 Transaction in Relation to Energy Transfer Period

Informative

This 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 Hierarchy

┌───────────────────────────────────────────────────────────┐
│ 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 StatusNotification messages: Charging, SuspendedEV, SuspendedEVSE.
  • Some EVs don't go to SuspendedEV state — they might trickle charge instead.
  • Some Charge Points don't have an electrical meter.

3.7 Transaction-Related Messages

Normative

Transaction-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.req messages

Delivery Rules

  1. 1 The Charge Point SHOULD deliver transaction-related messages in chronological order as soon as possible.
  2. 2 When offline, the Charge Point MUST queue transaction-related messages that it would have sent if online.
  3. 3 Non-transaction-related messages MAY be delivered immediately without waiting for the queue to empty — they skip ahead.
  4. 4 New transaction-related messages SHALL wait until the queue has been emptied.
  5. 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. 1 First failure → wait 60s → retry
  2. 2 Second failure → wait 120s → retry
  3. 3 Third failure → discard message, continue with next

7. Identifiers & Connectors

Normative

This 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:

  • StatusNotification with ConnectorId=0 reports errors/status for the Charge Point itself (not a specific connector).
  • ChargePointMaxProfile (smart charging) can only be set at ConnectorId=0.
  • Operations initiated by the CS with ConnectorId=0 address the entire CP (e.g., ChangeAvailability with 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 parentIdTag element in IdTagInfo.
  • Two idTags are in the same group if their parentIdTag values match.
  • The parentIdTag value has the same data type (IdToken / CiString20Type) as an idTag, but it may not represent an actual valid IdToken.
  • The parentIdTag value SHOULD NOT be used for comparison against a presented Token value.

8. Reservations & Data Transfer

Informative

3.11 Reservations

Reservation is possible using the ReserveNow operation:

  • Reserves a Charge Point until a certain expiry time for a specific idTag.
  • A parentIdTag may be included for "group" reservations.
  • Can reserve a specific connector (connectorId > 0) or any connector (connectorId = 0).
  • A reservation is released when:
    • The reserved idTag is used on the reserved connector.
    • The expiry time is reached.
    • The reservation is explicitly canceled (CancelReservation).
ReserveNow.req
{
  "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
}
ReserveNow.conf
{
  "status": "Accepted" | "Faulted" | "Occupied" | "Rejected" | "Unavailable"
}
CancelReservation.req
{
  "reservationId": integer
}
CancelReservation.conf
{
  "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.

DataTransfer.req
{
  "vendorId": "string (max 255)",    // REQUIRED — identifies the vendor
  "messageId": "string (max 50)",    // optional — identifies the message type
  "data": "string"                   // optional — payload data
}
DataTransfer.conf
{
  "status": "Accepted" | "Rejected" | "UnknownMessageId" | "UnknownVendorId",
  "data": "string"  // optional — response payload
}

9. Smart Charging

Normative

With 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.1

Three 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.2

It 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.3

The 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.4

Three 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 minChargingRate field 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.req with TxProfile purpose.

Local Smart Charging

  • Controlled locally by a Local Controller.
  • The Local Controller implements OCPP and acts as a proxy for group members.
  • Uses SetChargingProfile.req with ChargePointMaxProfile purpose on ConnectorId 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.6

If 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

Informative

The 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

Normative

3.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.

MeterValue Structure
{
  "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 Reference

This 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

Authorize.req
{
  "idTag": "string (max 20)"  // REQUIRED
}
Authorize.conf
{
  "idTagInfo": {
    "status": "Accepted" | "Blocked" | "Expired" | "Invalid" | "ConcurrentTx",
    "expiryDate": "date-time",
    "parentIdTag": "string (max 20)"
  }
}

BootNotification

BootNotification.req
{
  "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)"
}
BootNotification.conf
{
  "status": "Accepted" | "Pending" | "Rejected",
  "currentTime": "date-time",
  "interval": integer
}

Heartbeat

Heartbeat.req
{}
Heartbeat.conf
{
  "currentTime": "date-time"
}

StartTransaction

StartTransaction.req
{
  "connectorId": integer,
  "idTag": "string (max 20)",
  "meterStart": integer,
  "timestamp": "date-time",
  "reservationId": integer
}
StartTransaction.conf
{
  "idTagInfo": {
    "status": "Accepted" | "Blocked" | "Expired" | "Invalid" | "ConcurrentTx",
    "expiryDate": "date-time",
    "parentIdTag": "string (max 20)"
  },
  "transactionId": integer
}

StopTransaction

StopTransaction.req
{
  "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]
}
StopTransaction.conf
{
  "idTagInfo": { ... }
}

StatusNotification

StatusNotification.req
{
  "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)"
}
StatusNotification.conf
{}

MeterValues

MeterValues.req
{
  "connectorId": integer,
  "transactionId": integer,
  "meterValue": [MeterValue]
}
MeterValues.conf
{}

ChangeAvailability

ChangeAvailability.req
{
  "connectorId": integer,
  "type": "Inoperative" | "Operative"
}
ChangeAvailability.conf
{
  "status": "Accepted" | "Rejected" | "Scheduled"
}

ChangeConfiguration

ChangeConfiguration.req
{
  "key": "string (max 50)",
  "value": "string (max 500)"
}
ChangeConfiguration.conf
{
  "status": "Accepted" | "Rejected" | "RebootRequired" | "NotSupported"
}

ClearCache

ClearCache.req
{}
ClearCache.conf
{
  "status": "Accepted" | "Rejected"
}

GetConfiguration

GetConfiguration.req
{
  "key": ["string (max 50)"]
}
GetConfiguration.conf
{
  "configurationKey": [
    { "key": "string", "readonly": boolean, "value": "string" }
  ],
  "unknownKey": ["string"]
}

RemoteStartTransaction

RemoteStartTransaction.req
{
  "connectorId": integer,
  "idTag": "string (max 20)",
  "chargingProfile": { ... }
}
RemoteStartTransaction.conf
{
  "status": "Accepted" | "Rejected"
}

RemoteStopTransaction

RemoteStopTransaction.req
{
  "transactionId": integer
}
RemoteStopTransaction.conf
{
  "status": "Accepted" | "Rejected"
}

Reset

Reset.req
{
  "type": "Hard" | "Soft"
}
Reset.conf
{
  "status": "Accepted" | "Rejected"
}

UnlockConnector

UnlockConnector.req
{
  "connectorId": integer
}
UnlockConnector.conf
{
  "status": "Unlocked" | "UnlockFailed" | "NotSupported"
}

DataTransfer

DataTransfer.req
{
  "vendorId": "string (max 255)",
  "messageId": "string (max 50)",
  "data": "string"
}
DataTransfer.conf
{
  "status": "Accepted" | "Rejected" | "UnknownMessageId" | "UnknownVendorId",
  "data": "string"
}

Firmware Management

GetDiagnostics

GetDiagnostics.req
{
  "location": "uri-string",
  "retries": integer,
  "retryInterval": integer,
  "startTime": "date-time",
  "stopTime": "date-time"
}
GetDiagnostics.conf
{
  "fileName": "string (max 255)"
}

DiagnosticsStatusNotification

DiagnosticsStatusNotification.req
{
  "status": "Idle" | "Uploaded" | "UploadFailed" | "Uploading"
}
DiagnosticsStatusNotification.conf
{}

FirmwareStatusNotification

FirmwareStatusNotification.req
{
  "status": "Downloaded" | "DownloadFailed" | "Downloading" | "Idle" | "InstallationFailed" | "Installing" | "Installed"
}
FirmwareStatusNotification.conf
{}

UpdateFirmware

UpdateFirmware.req
{
  "location": "uri-string",
  "retrieveDate": "date-time",
  "retries": integer,
  "retryInterval": integer
}
UpdateFirmware.conf
{}

Local Auth List Management

GetLocalListVersion

GetLocalListVersion.req
{}
GetLocalListVersion.conf
{
  "listVersion": integer
}

SendLocalList

SendLocalList.req
{
  "listVersion": integer,
  "updateType": "Differential" | "Full",
  "localAuthorizationList": [
    { "idTag": "string", "idTagInfo": { ... } }
  ]
}
SendLocalList.conf
{
  "status": "Accepted" | "Failed" | "NotSupported" | "VersionMismatch"
}

Remote Trigger

TriggerMessage

TriggerMessage.req
{
  "requestedMessage": "BootNotification" | "DiagnosticsStatusNotification" | "FirmwareStatusNotification" | "Heartbeat" | "MeterValues" | "StatusNotification",
  "connectorId": integer
}
TriggerMessage.conf
{
  "status": "Accepted" | "Rejected" | "NotImplemented"
}

Smart Charging

SetChargingProfile

SetChargingProfile.req
{
  "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
    }
  }
}
SetChargingProfile.conf
{
  "status": "Accepted" | "Rejected" | "NotSupported"
}

ClearChargingProfile

ClearChargingProfile.req
{
  "id": integer,
  "connectorId": integer,
  "chargingProfilePurpose": "ChargePointMaxProfile" | "TxDefaultProfile" | "TxProfile",
  "stackLevel": integer
}
ClearChargingProfile.conf
{
  "status": "Accepted" | "Unknown"
}

GetCompositeSchedule

GetCompositeSchedule.req
{
  "connectorId": integer,
  "duration": integer,
  "chargingRateUnit": "A" | "W"
}
GetCompositeSchedule.conf
{
  "status": "Accepted" | "Rejected",
  "connectorId": integer,
  "scheduleStart": "date-time",
  "chargingSchedule": { ... }
}

12. Reference

Appendix

Connector 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.

Connector Status State Machine
                   ┌──────────┐
         ┌─────────│ 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

OCPP 1.6 Introduction - CSMS Developer Guide. Based on Open Charge Point Protocol 1.6, Edition 2 FINAL (2017-09-28).