Operations Initiated by Charge Point - CSMS Developer Guide
Based on Open Charge Point Protocol 1.6, Edition 2 FINAL (2017-09-28). This guide covers all messages that a Charge Point sends to the Central System, including authorization, transactions, status reporting, metering, and diagnostics.
1. General Conventions
IntroductionThese are the messages that a Charge Point (CP) sends to the Central System (CS). In OCPP-J (WebSocket/JSON), every request is a CALL [2, messageId, action, payload] and every response is a CALLRESULT [3, messageId, payload].
Connector Numbering (Section 3.8)
ConnectorIds are numbered consistently across the protocol:
| 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 |
Timestamp Format (Section 3.15)
All timestamps in OCPP 1.6 use ISO 8601 combined date and time format:
YYYY-MM-DDTHH:mm:ss[.sss]Z- Time precision: at least seconds precision.
- The CP MAY include sub-second precision (e.g., milliseconds); the CS MUST accept it.
- Timezone designator:
Z(UTC recommended) or+HH:mm/-HH:mmoffset. - CPs SHOULD be configured with UTC time. If a CP uses local time in a DST-observing timezone, timestamps may be ambiguous during DST transitions. The CS SHOULD be robust against such anomalies.
Transaction-Related Messages Overview (Section 3.7)
Transaction-related messages are: StartTransaction.req, StopTransaction.req,
and periodic/clock-aligned MeterValues.req messages.
Key delivery rules:
- The CP SHOULD deliver transaction-related messages in chronological order as soon as possible.
- When offline, the CP MUST queue transaction-related messages that it would have sent if online.
- Non-transaction-related messages (e.g., Authorize, StatusNotification) MAY be delivered immediately without waiting for the queue to empty -- they skip ahead to avoid delaying customers.
- New transaction-related messages SHALL wait until the queue has been emptied to ensure chronological delivery.
- The CS should process historical queued messages the same as any other -- timestamps may be significantly in the past.
Retry behavior (controlled by configuration keys):
| Configuration Key | Description |
|---|---|
TransactionMessageAttempts | Number of retry attempts for failed transaction-related messages. |
TransactionMessageRetryInterval | Base interval (seconds) between retries. Actual wait = interval x (number of preceding transmissions of same message). |
Backoff example: TransactionMessageAttempts=3, TransactionMessageRetryInterval=60
- First failure → wait 60s → retry
- Second failure → wait 120s → retry
- Third failure → discard message, continue with next transaction-related message
It is permissible for the CP to skip a transaction-related message if and only if the CS repeatedly reports a failure to process it. This prevents one bad message from blocking all subsequent transaction messages.
3. Boot Notification (4.2)
CoreAfter start-up, the CP informs the CS about its identity and configuration. The CS decides whether to accept the CP.
When to Send:
- The CP SHALL send
BootNotification.reqeach time it boots or reboots. - Between physical power-on and a successful BootNotification (where CS returns
AcceptedorPending), the CP SHALL NOT send any other requests to the CS. - On reconnection (without reboot): the CP SHOULD NOT send a
BootNotification.requnless one or more of the fields have changed since the last successful connection.
Request & Response
BootNotification.req
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
chargePointVendor | string | **Yes** | max: 20 | Vendor of the CP. |
chargePointModel | string | **Yes** | max: 20 | Model of the CP. |
chargePointSerialNumber | string | No | max: 25 | Serial number of the CP. |
chargeBoxSerialNumber | string | No | max: 25 | Serial number of the charge box. |
firmwareVersion | string | No | max: 50 | Firmware version of the CP. |
iccid | string | No | max: 20 | ICCID of the modem's SIM card. |
imsi | string | No | max: 20 | IMSI of the modem's SIM card. |
meterType | string | No | max: 25 | Type of the main power meter. |
meterSerialNumber | string | No | max: 25 | Serial number of the main power meter. |
{
"chargePointVendor": "VendorX",
"chargePointModel": "SingleSocket",
"chargePointSerialNumber": "CP-001",
"firmwareVersion": "1.2.3"
}BootNotification.conf
| Field | Type | Required | Description |
|---|---|---|---|
status | string (enum) | Yes | Registration status. |
currentTime | string (date-time) | Yes | CS's current time (for clock sync). |
interval | integer | Yes | Heartbeat/retry interval in seconds. |
status enum values:
| Value | Meaning |
|---|---|
Accepted | CP is accepted. Normal operation can begin. |
Pending | CS wants to retrieve/set info before accepting. CP SHALL NOT send requests unless instructed via TriggerMessage. |
Rejected | CP is not accepted. CP SHALL NOT send any messages until retry interval has elapsed. |
{
"status": "Accepted",
"currentTime": "2025-01-15T10:30:00Z",
"interval": 300
}CSMS Implementation Notes
When responding Accepted:
The CP will use the interval as its heartbeat interval. It is RECOMMENDED that the CP syncs its clock with currentTime.
When responding other than Accepted:
The interval value
specifies the minimum wait time before the CP sends the next BootNotification.req. If interval is 0, the CP picks its
own interval to avoid flooding the CS.
When Rejected:
- The CP SHALL NOT send any OCPP message to the CS until the retry interval has expired.
- The CP MAY close its communication channel or shut down its communication hardware.
- The CS MAY close the communication channel to free up system resources.
- The CS SHALL NOT respond to any CP-initiated messages and SHOULD NOT initiate any messages.
When Pending:
- The communication channel SHOULD NOT be closed by either the CP or the CS.
- The CS MAY send request messages to retrieve information from the CP or change its configuration.
- The CP SHALL NOT send request messages to the CS unless instructed via
TriggerMessage.req. - While in pending state,
RemoteStartTransaction.reqandRemoteStopTransaction.reqare NOT allowed.
Initial Status Reporting After Boot
After the CS accepts the CP (BootNotification.conf with Accepted), the CP
SHOULD send a StatusNotification.req for each of its connectors (including connectorId 0) to report the current status. This
ensures the CS has an up-to-date view of the CP's state after boot.
Transactions Before Acceptance (Section 4.2.1)
A CP Operator MAY choose to configure a CP to accept transactions before the CP is accepted by a CS. However, it is uncertain if those transactions can ever be delivered to the CS.
After a restart, the CP MUST again contact the CS and SHALL send a BootNotification.req. If the CP fails to receive a response and has no non-volatile real-time clock, it may
not have a valid date/time, making it impossible to later determine the date/time of
transactions.
Recommendation: It is usually advisable to deny all charging services at a CP if the CP has never before been Accepted by the CS, since
users cannot be authenticated and running transactions could conflict with provisioning processes.
4. Data Transfer (4.3)
CoreUsed to send vendor-specific information not supported by standard OCPP messages. DataTransfer
is bidirectional -- the CS can also send DataTransfer.req to the
CP.
Request & Response
DataTransfer.req
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
vendorId | string | **Yes** | max: 255 | Identifies the vendor (SHOULD be reversed DNS namespace, e.g., com.vendor.name). |
messageId | string | No | max: 50 | Additional identification for the message/implementation. |
data | string | No | Unbounded | Vendor-specific data payload. |
{
"vendorId": "com.example.vendor",
"messageId": "CustomStatus",
"data": "{\"temperature\": 42}"
}DataTransfer.conf
| Field | Type | Required | Description |
|---|---|---|---|
status | string (enum) | **Yes** | Status of the data transfer. |
data | string | No | Response data. |
status enum values:
| Value | Meaning |
|---|---|
Accepted | Message accepted and data processed. |
Rejected | Message rejected by the recipient. |
UnknownMessageId | The messageId is not recognized. |
UnknownVendorId | The vendorId is not recognized. The data element SHALL NOT be present. |
{
"status": "Accepted",
"data": "{\"ack\": true}"
}CSMS Implementation Notes
- If the CS has no implementation for the
vendorId, returnUnknownVendorId(withoutdata). - If the
vendorIdis known butmessageIddoesn't match, returnUnknownMessageId. - The length of
datain both the request and response is undefined and should be agreed upon by all parties. - The
vendorIdSHOULD be a value from the reversed DNS namespace (e.g.,com.vendor.name).
Warning: Use DataTransfer with extreme caution -- it impacts interoperability with systems that do not implement the same vendor extension.
5. Diagnostics Status Notification (4.4)
Firmware ManagementInforms the CS about the status of a diagnostics upload initiated by GetDiagnostics.req.
Request & Response
DiagnosticsStatusNotification.req
| Field | Type | Required | Description |
|---|---|---|---|
status | string (enum) | Yes | Upload status. |
status enum values:
| Value | Meaning |
|---|---|
Idle | Not uploading. Only sent after receipt of a TriggerMessage when not busy. |
Uploaded | Upload completed successfully. |
UploadFailed | Upload failed. |
Uploading | Currently uploading diagnostics. |
{
"status": "Uploaded"
}{}When to Send
- The CP SHALL send this to inform the CS about the status of a diagnostics upload initiated by
GetDiagnostics.req. - The CP SHALL send
Uploadingwhen it starts uploading, followed byUploadedon success orUploadFailedon failure. - The CP SHALL only send status
Idleafter receipt of aTriggerMessage.reqwhen it is not currently busy uploading diagnostics.
6. Firmware Status Notification (4.5)
Firmware ManagementInforms the CS about the progress of a firmware update initiated by UpdateFirmware.req.
Request & Response
FirmwareStatusNotification.req
| Field | Type | Required | Description |
|---|---|---|---|
status | string (enum) | Yes | Firmware update status. |
status enum values:
| Value | Meaning |
|---|---|
Downloaded | Firmware downloaded successfully. |
DownloadFailed | Firmware download failed. |
Downloading | Currently downloading firmware. |
Idle | Not downloading/installing. Only sent after TriggerMessage when not busy. |
InstallationFailed | Firmware installation failed. |
Installing | Currently installing firmware. |
Installed | Firmware installed successfully. |
{
"status": "Installed"
}{}When to Send
Firmware update lifecycle:
Downloading → Downloaded (or DownloadFailed) → Installing → Installed (or
InstallationFailed)- The CP SHALL send notifications as it progresses through the firmware update lifecycle.
- Status
IdleSHALL only be sent after aTriggerMessage.reqwhen the CP is not busy. - After a successful firmware installation, the CP will typically reboot and then send a
BootNotification.req.
CSMS Note: The CS SHALL respond with the empty FirmwareStatusNotification.conf. These PDUs keep the CS updated with the status of the update process.
7. Heartbeat (4.6)
CoreLets the CS know the CP is still connected. Also provides clock synchronization.
When to Send:
- The CP SHALL send
Heartbeat.reqat a configurable interval to indicate it is alive. - The CP MAY skip sending a heartbeat if another PDU was already sent within the heartbeat interval. The CS SHOULD treat any received PDU as proof of availability.
- Over WebSocket (OCPP-J), heartbeats are not mandatory, but at least one heartbeat per 24 hours is advised for time synchronization.
Request & Response
{}{
"currentTime": "2025-01-15T10:35:00Z"
}Heartbeat.conf fields:
| Field | Type | Required | Description |
|---|---|---|---|
currentTime | string (date-time) | Yes | CS's current time (ISO 8601). |
CSMS Implementation Notes
- The CS SHALL respond with the current time. It is RECOMMENDED that the CP uses this to synchronize its internal clock.
- The CS SHOULD treat receipt of any message from a CP the same way as a heartbeat for availability tracking.
WebSocket Ping/Pong vs OCPP Heartbeat
WebSocket Ping/Pong frames can serve as a connection keepalive mechanism, but they cannot replace the OCPP Heartbeat for time synchronization (since Pong frames do not carry a server timestamp).
Even when using WebSocket Ping/Pong, at least one OCPP Heartbeat per 24 hours is recommended to ensure correct clock synchronization.
The WebSocketPingInterval configuration key controls the interval for WebSocket Ping frames (0 = disabled).
8. Meter Values (4.7)
CoreThe CP sends sampled electrical meter data (energy, power, current, voltage, etc.) to the CS.
This can be configured via the ChangeConfiguration.req message to set acquisition intervals and which measurands to report.
Request & Response
MeterValues.req
| Field | Type | Required | Description |
|---|---|---|---|
connectorId | integer | Yes | Connector ID. Must be >= 0. 0 = main energy meter / entire CP. |
transactionId | integer | No | Transaction these values relate to. May be omitted if no transaction. |
meterValue | MeterValue[] | Yes | One or more sets of meter readings. |
MeterValue object:
| Field | Type | Required | Description |
|---|---|---|---|
timestamp | string (date-time) | Yes | When the values were captured. |
sampledValue | SampledValue[] | Yes | One or more measured values at this point in time. |
{
"connectorId": 1,
"transactionId": 12345,
"meterValue": [
{
"timestamp": "2025-01-15T10:40:00Z",
"sampledValue": [
{
"value": "1500",
"measurand": "Energy.Active.Import.Register",
"unit": "Wh",
"context": "Sample.Periodic"
},
{
"value": "7200",
"measurand": "Power.Active.Import",
"unit": "W",
"context": "Sample.Periodic"
}
]
}
]
}Response: MeterValues.conf is an
empty body ({}).
SampledValue Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
value | string | **Yes** | — | The measured value as a string. |
context | string (enum) | No | Sample.Periodic | Reason/event that triggered the reading. |
format | string (enum) | No | Raw | Raw = numeric, SignedData = opaque signed binary (hex). |
measurand | string (enum) | No | Energy.Active.Import.Register | Type of value being measured. |
phase | string (enum) | No | — | Phase of the electric installation. |
location | string (enum) | No | Outlet | Where the measurement is taken. |
unit | string (enum) | No | Wh | Unit of measure. |
Default behavior: When all optional fields on a SampledValue are absent, the value is interpreted as a register reading of active import energy in Wh (Watt-hour).
context enum values
| Value | Description |
|---|---|
Interruption.Begin | Value at start of an interruption. |
Interruption.End | Value at end of an interruption. |
Sample.Clock | Clock-aligned periodic sample. |
Sample.Periodic | Regular periodic sample (from transaction start). |
Transaction.Begin | Value at start of a transaction. |
Transaction.End | Value at end of a transaction. |
Trigger | Value sampled in response to a TriggerMessage. |
Other | Any other reason. |
measurand enum values
| Value | Unit | Description |
|---|---|---|
Energy.Active.Export.Register | Wh/kWh | Energy exported (register). |
Energy.Active.Import.Register | Wh/kWh | Energy imported (register). Default. |
Energy.Reactive.Export.Register | varh/kvarh | Reactive energy exported (register). |
Energy.Reactive.Import.Register | varh/kvarh | Reactive energy imported (register). |
Energy.Active.Export.Interval | Wh/kWh | Energy exported since last interval. |
Energy.Active.Import.Interval | Wh/kWh | Energy imported since last interval. |
Energy.Reactive.Export.Interval | varh/kvarh | Reactive energy exported since last interval. |
Energy.Reactive.Import.Interval | varh/kvarh | Reactive energy imported since last interval. |
Power.Active.Export | W/kW | Instantaneous active power exported. |
Power.Active.Import | W/kW | Instantaneous active power imported. |
Power.Offered | W/kW | Max power offered to EV (smart charging). |
Power.Reactive.Export | var/kvar | Instantaneous reactive power exported. |
Power.Reactive.Import | var/kvar | Instantaneous reactive power imported. |
Power.Factor | — | Power factor. |
Current.Import | A | Instantaneous current imported. |
Current.Export | A | Instantaneous current exported. |
Current.Offered | A | Max current offered to EV (smart charging). |
Voltage | V | Instantaneous voltage. |
Frequency | — | Grid frequency. |
Temperature | Celsius/K/F | Temperature reading. |
SoC | Percent | State of Charge of the EV battery. |
RPM | — | Fan speed in RPM. |
location enum values
| Value | Description |
|---|---|
Cable | Measurement in the cable. |
EV | Measurement inside the EV. |
Inlet | Measurement at grid connection (inlet). |
Outlet | Measurement at connector (outlet). Default. |
Body | Measurement in the body of the CP. |
phase and unit enum values
phase: L1, L2, L3, N, L1-N, L2-N, L3-N, L1-L2, L2-L3, L3-L1
unit: Wh, kWh, varh, kvarh, W, kW, VA, kVA, var, kvar, A, V, K, Celcius, Celsius, Fahrenheit, Percent
Note: Both Celcius (legacy typo) and Celsius are valid values
for backward compatibility.
CSMS Implementation Notes
- The CS SHALL respond with
MeterValues.conf(empty object). - The CS SHOULD apply sanity checks to the data, but SHOULD NOT ever refuse to respond (failure to respond causes the CP to retry the same message).
connectorId = 0: values are for the entire CP / main energy meter.transactionIdmay be omitted if there is no active transaction or values are from the main meter.- Phase reporting: The CP SHALL report all phase-dependent values from the electrical
meter point of view when the phase field is absent. Use
ConnectorPhaseRotationconfig key to determine physical phase mapping. - format = SignedData: Experimental field. Opaque digitally signed binary data as hex.
Transaction-Related: Periodic or clock-aligned MeterValues.req messages
sent during a transaction are transaction-related messages. When offline, the
CP MUST queue these and transmit when connection is restored.
Relevant Configuration Keys
| Key | Description |
|---|---|
MeterValueSampleInterval | Seconds between sampled meter data transmissions (0 = disabled). |
MeterValuesSampledData | Comma-separated list of measurands for periodic sampling. |
MeterValuesSampledDataMaxLength | Max elements in the sampled data list. |
ClockAlignedDataInterval | Seconds for clock-aligned meter data intervals (0 = disabled). Starts from midnight. |
MeterValuesAlignedData | Comma-separated list of measurands for clock-aligned readings. |
MeterValuesAlignedDataMaxLength | Max elements in the aligned data list. |
StopTxnSampledData | Measurands included in TransactionData of StopTransaction.req (sampled). |
StopTxnSampledDataMaxLength | Max elements in StopTxnSampledData. |
StopTxnAlignedData | Measurands included in TransactionData of StopTransaction.req (clock-aligned). |
StopTxnAlignedDataMaxLength | Max elements in StopTxnAlignedData. |
ConnectorPhaseRotation | Comma-separated connector-phase rotation values (e.g., 0.RST, 1.RST, 2.RTS). |
9. Start Transaction (4.8)
CoreInforms the CS that a charging transaction has started at a connector.
Conceptual Hierarchy (Section 3.6)
A Transaction is part of a larger Charging Session and may contain multiple Energy Transfer Periods (actual power flow to the EV).
Charging Session (first user/EV interaction → station available again)
└── Transaction (all preconditions met → irrevocably ends)
├── Energy Offer Period (EVSE ready and willing)
│ └── Energy Transfer Period (actual energy flow)
├── Energy Offer Suspend Period (e.g., smart charging)
└── Energy Offer Period
└── Energy Transfer PeriodWhen to Send:
- The CP SHALL send
StartTransaction.reqwhen energy delivery has started. - If this transaction ends a reservation, the
reservationIdMUST be included.
Request & Response
StartTransaction.req
| Field | Type | Required | Description |
|---|---|---|---|
connectorId | integer | Yes | Connector where the transaction started. Must be > 0. |
idTag | string (max 20) | Yes | Identifier that authorized the transaction. |
meterStart | integer | Yes | Meter value in Wh at the start of the transaction. |
timestamp | string (date-time) | Yes | When the transaction started. |
reservationId | integer | No | ID of the reservation this transaction ends. |
{
"connectorId": 1,
"idTag": "ABC12345",
"meterStart": 15000,
"timestamp": "2025-01-15T10:30:00Z",
"reservationId": 42
}StartTransaction.conf
| Field | Type | Required | Description |
|---|---|---|---|
transactionId | integer | Yes | CS-assigned transaction ID. |
idTagInfo | object | Yes | Authorization status info (same structure as Authorize.conf). |
idTagInfo.status | string (enum) | Yes | Accepted, Blocked, Expired, Invalid, ConcurrentTx |
idTagInfo.expiryDate | date-time | No | Token expiry date. |
idTagInfo.parentIdTag | string (max 20) | No | Parent identifier. |
{
"transactionId": 12345,
"idTagInfo": {
"status": "Accepted",
"expiryDate": "2025-12-31T23:59:59Z"
}
}CSMS Implementation Notes
- The CS MUST verify the idTag validity. The identifier might have been authorized locally by the CP using outdated information (e.g., it could have been blocked since it was cached).
- The response MUST include a
transactionId(integer assigned by the CS) and an authorization status. - The CS SHOULD apply sanity checks to the data but SHOULD NOT ever cause the CS to not
respond with a
StartTransaction.conf. Failing to respond will cause the CP to retry the same message. - If the CP has an Authorization Cache, it SHALL update the cache entry with
the
IdTagInfofrom the response.
Offline Authorization Recovery (Non-Accepted StartTransaction.conf)
When the CP authorized a transaction offline (locally) and later receives a StartTransaction.conf with a status other than Accepted, the transaction may still be ongoing:
| Config Key | Value | Behavior |
|---|---|---|
StopTransactionOnInvalidId | true | CP SHALL stop the transaction normally, setting reason to DeAuthorized. If the CP can lock the charging cable, it SHOULD keep it locked until the owner presents their identifier. |
StopTransactionOnInvalidId | false | CP SHALL only stop energy delivery to the vehicle but SHALL NOT end the transaction itself. |
An operator MAY configure MaxEnergyOnInvalidId (in Wh) to allow a minimum amount of energy delivery on an invalid id so the EV can drive
away.
10. Status Notification (4.9)
CoreInforms the CS about a status change or error on a connector or the CP itself.
Request & Response
StatusNotification.req
| Field | Type | Required | Description |
|---|---|---|---|
connectorId | integer | Yes | Connector ID. 0 = entire CP. |
errorCode | string (enum) | Yes | Error code. NoError if no error. |
status | string (enum) | Yes | Current status of the connector. |
timestamp | string (date-time) | No | When the status change occurred. |
info | string (max 50) | No | Additional free-text info. |
vendorId | string (max 255) | No | Vendor-specific identifier. |
vendorErrorCode | string (max 50) | No | Vendor-specific error code. |
status enum values:
| Value | Description |
|---|---|
Available | Connector is available for a new user. |
Preparing | Connector is occupied, user interaction needed before charging. |
Charging | Energy is actively being delivered. |
SuspendedEV | Charging suspended by the EV. |
SuspendedEVSE | Charging suspended by the EVSE (e.g., smart charging). |
Finishing | Transaction stopped, user action required (e.g., remove cable). |
Reserved | Connector is reserved for a specific idTag. |
Unavailable | Connector is not available for charging (admin/maintenance). |
Faulted | Error condition preventing charging. |
ConnectorId 0: Only Available, Unavailable, and Faulted are valid. The
status of ConnectorId 0 has no direct connection to individual connectors.
errorCode enum values
| Value | Description |
|---|---|
ConnectorLockFailure | Failed to lock/unlock the connector. |
EVCommunicationError | Communication failure with the EV. Only valid with: Preparing, SuspendedEVSE, Finishing. |
GroundFailure | Ground fault detected. |
HighTemperature | Temperature too high. |
InternalError | Internal hardware/software error. |
LocalListConflict | Conflict in local authorization list. |
NoError | No error to report. |
OtherError | Other unspecified error. |
OverCurrentFailure | Over-current protection triggered. |
PowerMeterFailure | Power meter failure. |
PowerSwitchFailure | Power switch failure. |
ReaderFailure | ID reader failure. |
ResetFailure | Reset failed. |
UnderVoltage | Under-voltage detected. |
OverVoltage | Over-voltage detected. |
WeakSignal | Wireless communication signal too weak. |
{
"connectorId": 1,
"errorCode": "NoError",
"status": "Available",
"timestamp": "2025-01-15T10:30:00Z"
}Response: StatusNotification.conf is an empty body ({}).
Connector Status Transition Matrix
Valid transitions between statuses for connectors with connectorId > 0:
| From \ To | Avail | Prep | Charg | SusEV | SusEVSE | Fin | Res | Unavail | Fault |
|---|---|---|---|---|---|---|---|---|---|
| Available | A2 | A3 | A4 | A5 | A7 | A8 | A9 | ||
| Preparing | B1 | B3 | B4 | B5 | B6 | B9 | |||
| Charging | C1 | C4 | C5 | C6 | C8 | C9 | |||
| SuspendedEV | D1 | D3 | D5 | D6 | D8 | D9 | |||
| SuspendedEVSE | E1 | E3 | E4 | E6 | E8 | E9 | |||
| Finishing | F1 | F2 | F8 | F9 | |||||
| Reserved | G1 | G2 | G8 | G9 | |||||
| Unavailable | H1 | H2 | H3 | H4 | H5 | H9 | |||
| Faulted | I1 | I2 | I3 | I4 | I5 | I6 | I7 | I8 |
Status Transition Event Descriptions
From Available
| Event | Description |
|---|---|
A2 | Usage initiated (e.g., insert plug, present idTag, push start button, RemoteStartTransaction.req). |
A3 | CP without authorization means — all prerequisites met and charging starts. |
A4 | Similar to A3 but the EV does not start charging. |
A5 | Similar to A3 but the EVSE does not allow charging. |
A7 | A ReserveNow message reserves the connector. |
A8 | A ChangeAvailability message sets the connector to Unavailable. |
A9 | A fault prevents further charging operations. |
From Preparing
| Event | Description |
|---|---|
B1 | Intended usage ended (plug removed, second idTag presentation, timeout via ConnectionTimeOut). |
B3 | All prerequisites for charging are met and charging starts. |
B4 | All prerequisites met but EV does not start charging. |
B5 | All prerequisites met but EVSE does not allow charging. |
B6 | Timed out — usage initiated but idTag not presented within timeout. |
B9 | A fault prevents further charging operations. |
From Charging
| Event | Description |
|---|---|
C1 | Charging session ends, no user action required (e.g., fixed cable removed on EV side). |
C4 | Charging stops upon EV request (e.g., S2 opened). |
C5 | Charging stops upon EVSE request (e.g., smart charging restriction). |
C6 | Transaction stopped by user or RemoteStopTransaction, further user action required. |
C8 | Charging session ends, connector scheduled to become Unavailable. |
C9 | A fault prevents further charging operations. |
From SuspendedEV
| Event | Description |
|---|---|
D1 | Charging session ends, no user action required. |
D3 | Charging resumes upon request of the EV (e.g., S2 closed). |
D5 | Charging suspended by EVSE (e.g., smart charging restriction). |
D6 | Transaction stopped, further user action required. |
D8 | Charging session ends, connector scheduled to become Unavailable. |
D9 | A fault prevents further charging operations. |
From SuspendedEVSE
| Event | Description |
|---|---|
E1 | Charging session ends, no user action required. |
E3 | Charging resumes because EVSE restriction is lifted. |
E4 | EVSE restriction lifted but EV does not start charging. |
E6 | Transaction stopped, further user action required. |
E8 | Charging session ends, connector scheduled to become Unavailable. |
E9 | A fault prevents further charging operations. |
From Finishing
| Event | Description |
|---|---|
F1 | All user actions completed. |
F2 | User restarts charging session — creates a new Transaction. |
F8 | All user actions completed, connector scheduled to become Unavailable. |
F9 | A fault prevents further charging operations. |
From Reserved
| Event | Description |
|---|---|
G1 | Reservation expires or CancelReservation message received. |
G2 | Reservation identity is presented (starts transaction flow). |
G8 | Reservation expires/cancelled, connector scheduled to become Unavailable. |
G9 | A fault prevents further charging operations. |
From Unavailable
| Event | Description |
|---|---|
H1 | Connector set Available by ChangeAvailability message. |
H2 | Connector set Available after user interaction with the CP. |
H3 | Connector set Available, no user action required to start charging. |
H4 | Similar to H3 but EV does not start charging. |
H5 | Similar to H3 but EVSE does not allow charging. |
H9 | A fault prevents further charging operations. |
From Faulted
| Event | Description |
|---|---|
I1-I8 | Fault is resolved and status returns to the pre-fault state. |
Faulted during a transaction: A Faulted status does
not necessarily stop the transaction. The CP may enter Faulted while a transaction is ongoing
(e.g., a non-critical hardware warning). When the fault is resolved, the connector returns to
its previous state.
CSMS Implementation Notes
- The CS SHALL respond with
StatusNotification.conf(empty object). - When
statusis notFaulted, the error condition should be considered a warning since charging operations are still possible. SuspendedEVSESHALL have precedence overSuspendedEVwhen both EV and EVSE suspend charging.Unavailablestatus set by ChangeAvailability MUST persist across reboots.- The CP MAY omit
StatusNotification.reqif a status was active for less thanMinimumStatusDurationseconds. - Messages MUST be sent in order of the events they describe.
When to Send:
- Whenever the status of a connector changes, or when an error occurs.
- After successful BootNotification (Accepted): the CP SHOULD send a StatusNotification.req for ConnectorId 0 and for each connector to report its current status.
- After reconnecting from offline: the CP SHOULD send a StatusNotification.req with its current status if the status changed while offline. The CP SHOULD NOT send PDUs for historical status changes.
Occupied State Split: The Occupied state from
previous OCPP versions is split into five statuses: Preparing, Charging, SuspendedEV, SuspendedEVSE, and Finishing. This results
in more StatusNotification.req PDUs being sent.
EV-Side Disconnect Behavior
| Config Key & Value | Status Sent | Transaction |
|---|---|---|
StopTransactionOnEVSideDisconnect = false | SuspendedEV, NoError | NOT stopped. |
StopTransactionOnEVSideDisconnect = true | Finishing, NoError | Stopped. Energy transfer not allowed until new transaction. |
Relevant Configuration Keys
| Key | Description |
|---|---|
MinimumStatusDuration | Minimum time (seconds) a status must be active before a StatusNotification.req is sent. |
ConnectorPhaseRotation | Describes the phase rotation for each connector relative to the grid. |
StopTransactionOnEVSideDisconnect | Controls whether a transaction is stopped when the EV-side cable is disconnected. |
UnlockConnectorOnEVSideDisconnect | Controls whether the connector is unlocked when the EV-side cable is disconnected. |
11. Stop Transaction (4.10)
CoreInforms the CS that a charging transaction has stopped.
When to Send:
- The CP SHALL send
StopTransaction.reqwhen a transaction is stopped (for any reason). - The CP SHALL NOT send an
Authorize.reqbefore stopping a transaction if the presented idTag is the same as the idTag that started the transaction. - When the idTag used to stop a transaction differs from the one used to
start it, the CP SHALL first send an
Authorize.reqfor the new idTag. A user is allowed to stop a transaction if their idTag has the sameparentIdTagas the idTag that started the transaction (group authorization).
Request & Response
StopTransaction.req
| Field | Type | Required | Description |
|---|---|---|---|
transactionId | integer | Yes | Transaction ID (assigned by CS in StartTransaction.conf). |
meterStop | integer | Yes | Meter value in Wh at the end of the transaction. |
timestamp | string (date-time) | Yes | When the transaction stopped. |
idTag | string (max 20) | No | Identifier that requested the stop. MAY be omitted if CP itself stopped it. |
reason | string (enum) | No | Reason the transaction was stopped. |
transactionData | MeterValue[] | No | Optional detailed meter data for the transaction. |
reason enum values:
| Value | Description |
|---|---|
EmergencyStop | Emergency stop button was used. |
EVDisconnected | Disconnecting of cable/vehicle. |
HardReset | A hard reset command was received. |
Local | Stopped locally at the CP (normal user action). Default when omitted. |
Other | Any other reason. |
PowerLoss | Loss of power. |
Reboot | A locally initiated reboot/restart. |
Remote | Stopped remotely via RemoteStopTransaction.req. |
SoftReset | A soft reset command was received. |
UnlockCommand | Stopped by UnlockConnector.req. |
DeAuthorized | The idTag was de-authorized (blocked/expired after start). |
{
"transactionId": 12345,
"meterStop": 18500,
"timestamp": "2025-01-15T12:00:00Z",
"idTag": "ABC12345",
"reason": "Local",
"transactionData": [
{
"timestamp": "2025-01-15T11:00:00Z",
"sampledValue": [
{
"value": "16500",
"measurand": "Energy.Active.Import.Register",
"unit": "Wh",
"context": "Sample.Periodic"
}
]
}
]
}StopTransaction.conf
| Field | Type | Required | Description |
|---|---|---|---|
idTagInfo | object | No | Authorization status info. Only present if an idTag was provided in the request. |
idTagInfo.status | string (enum) | Yes* | Accepted, Blocked, Expired, Invalid, ConcurrentTx (*if idTagInfo present) |
idTagInfo.expiryDate | date-time | No | Token expiry date. |
idTagInfo.parentIdTag | string (max 20) | No | Parent identifier. |
{
"idTagInfo": {
"status": "Accepted"
}
}{}CSMS Implementation Notes
- The CS cannot prevent a transaction from stopping. It MAY only inform the CP about the idTag status (for cache updates).
- The
idTagin the request MAY be omitted when the CP itself stops the transaction (e.g., requested to reset). - If
reasonis omitted and the transaction ended normally, the CS SHOULD assumeLocal. - The
transactionDataelement is a container for MeterValues using the same structure asMeterValues.req. The measurands included are controlled byStopTxnSampledDataandStopTxnAlignedDataconfig keys. - When both
StopTxnAlignedDataandStopTxnSampledDataare empty strings, the CP SHALL NOT include meter values inStopTransaction.req. - The CS SHOULD NOT ever refuse to respond — failure to respond causes the CP to retry.
- If the CP has an Authorization Cache, it SHALL update the cache entry with the
IdTagInfofrom the response. - The CP SHALL unlock the cable (if not permanently attached) as part of normal transaction termination.
Transaction-Related: StopTransaction.req is
a transaction-related message. When offline, the CP MUST queue these messages
and transmit when connection is restored. Retry behavior follows the backoff formula in General
Conventions.
Cable Disconnect Behavior
The CP MAY unlock the cable and/or stop a running transaction when the cable is disconnected at the EV. The behavior depends on configuration:
| Config Key & Value | Effect |
|---|---|
StopTransactionOnEVSideDisconnect = false | Transaction SHALL NOT be stopped. If EV is reconnected, energy transfer is allowed again. With UnlockConnectorOnEVSideDisconnect = false, the connector SHALL remain locked until the user presents the identifier. |
StopTransactionOnEVSideDisconnect = true | Transaction SHALL be stopped. Energy transfer not allowed until new transaction. If UnlockConnectorOnEVSideDisconnect is also true, the connector will be unlocked. |
Priority rule: If StopTransactionOnEVSideDisconnect is set to false, this SHALL have
priority over UnlockConnectorOnEVSideDisconnect. Cables always remain locked when StopTransactionOnEVSideDisconnect is false.
Security note: Setting StopTransactionOnEVSideDisconnect to true will prevent sabotage
acts to stop the energy flow by unplugging not-locked cables on EV side.