Migration Guide 2.0.1 → 2.1 Section E

Transactions Section — Migration Guide

Use cases E01–E17 (Transactions). Perspective: CSMS Developer.

7 Sections
17 Use Cases
E01 – E17

Created by tzi.app — your guide to migrating from OCPP 2.0.1 to OCPP 2.1.

1. Summary of Changes

High-Level Overview

Area Change Type Description
TransactionEventRequest New fields preconditioningStatus, evseSleep, costDetails added
TransactionType (transactionInfo) New fields operationMode, tariffId, transactionLimit added
TransactionEventResponse New fields transactionLimit, updatedPersonalMessageExtra added
TransactionEventResponse.totalCost Semantics expanded Can now be sent as running cost in Updated events, not just final cost in Ended
TriggerReasonEnumType New values CostLimitReached, LimitSet, OperationModeChanged, RunningCost, SoCLimitReached, TariffChanged, TariffNotAccepted, TxResumed added
ReasonEnumType (stoppedReason) New value ReqEnergyTransferRejected added
Connector status reporting Message changed StatusNotificationRequest replaced by NotifyEventRequest for connector state changes
E10 New scenario Timeout option added for permanently attached cables
E11 Clarification Explicit message-dropping order defined (intermediate messages first)
E12 Clarification Non-droppable triggerReasons specified for offline queued messages
E13 Clarification Specific retry configuration variables and algorithm documented
E15 Scope narrowed Now specifically covers ISO 15118 SessionStopReq(Terminate) flow
E16 New use case Transactions with Limits (cost, energy, time, SoC limits)
E17 New use case Resuming Transaction After Forced Reboot

2. Data Type & Schema Changes

2.1 TransactionEventRequest — New Optional Fields

2.0.1 TransactionEventRequest
{
  "eventType": "...",
  "timestamp": "...",
  "triggerReason": "...",
  "seqNo": 0,
  "transactionInfo": { ... },
  "offline": false,
  "numberOfPhasesUsed": 3,
  "cableMaxCurrent": 32,
  "reservationId": 456,
  "evse": { ... },
  "idToken": { ... },
  "meterValue": [ ... ]
}
2.1 TransactionEventRequest
{
  "eventType": "...",
  "timestamp": "...",
  "triggerReason": "...",
  "seqNo": 0,
  "transactionInfo": { ... },
  "offline": false,
  "numberOfPhasesUsed": 3,
  "cableMaxCurrent": 32,
  "reservationId": 456,
  "evse": { ... },
  "idToken": { ... },
  "meterValue": [ ... ],
  "preconditioningStatus": "...",  // NEW
  "evseSleep": false,              // NEW
  "costDetails": { ... }           // NEW
}
New Field Type Description
preconditioningStatus enum: Unknown, Ready, NotReady, Preconditioning BMS preconditioning status for the EV battery
evseSleep boolean true when EVSE electronics are in sleep mode
costDetails CostDetailsType Cost calculated locally by the Charging Station

Action Required: Add handling for preconditioningStatus if your CSMS needs to track battery conditioning state. Add handling for evseSleep if your CSMS needs to track EVSE power state. Add handling for costDetails if you want to compare CS-calculated costs with CSMS-calculated costs.

2.2 TransactionType (transactionInfo) — New Fields

2.0.1 transactionInfo
{
  "transactionId": "...",
  "chargingState": "...",
  "timeSpentCharging": 3600,
  "stoppedReason": "...",
  "remoteStartId": 123
}
2.1 transactionInfo
{
  "transactionId": "...",
  "chargingState": "...",
  "timeSpentCharging": 3600,
  "stoppedReason": "...",
  "remoteStartId": 123,
  "operationMode": "...",         // NEW
  "tariffId": "...",              // NEW
  "transactionLimit": { ... }     // NEW
}
New Field Type Description
operationMode enum Current operation mode of the transaction
tariffId string (max 60) ID of the tariff currently in use
transactionLimit TransactionLimitType Active limits on the transaction (see E16)

Action Required: Store operationMode if your CSMS tracks charging modes. Store tariffId to link transactions with the applied tariff. Implement transactionLimit handling for the new E16 use case.

2.3 TransactionEventResponse — New Fields

2.0.1 TransactionEventResponse
{
  "totalCost": 12.50,
  "chargingPriority": 0,
  "idTokenInfo": { ... },
  "updatedPersonalMessage": { ... }
}
2.1 TransactionEventResponse
{
  "totalCost": 12.50,
  "chargingPriority": 0,
  "idTokenInfo": { ... },
  "updatedPersonalMessage": { ... },
  "transactionLimit": { ... },              // NEW
  "updatedPersonalMessageExtra": [ ... ]    // NEW
}
New Field Type Description
transactionLimit TransactionLimitType Set or update limits on the transaction from the CSMS side
updatedPersonalMessageExtra MessageContentType[] (max 4) Additional messages to display to user

TransactionLimitType New in 2.1

Field Type Description
maxCost number Max allowed cost in tariff currency
maxEnergy number Max energy in Wh
maxTime integer Max duration in seconds
maxSoC integer (0-100) Max State of Charge percentage

totalCost semantics change

Behavior OCPP 2.0.1 OCPP 2.1
In Ended response Final cost; omit = not free; 0.00 = free Same
In Updated response Not specified Running cost — can be sent during transaction to provide cost updates

Action Required: Implement transactionLimit in responses to set/update limits on active transactions (required for E16). Consider sending totalCost as running cost in Updated responses (especially when maxCost limit is active). Add support for updatedPersonalMessageExtra if your CSMS sends multiple user messages.

2.4 TriggerReasonEnumType — New Values

Value Version Description
CostLimitReached 2.1 only Cost limit on the transaction was reached
LimitSet 2.1 only A limit was set on the transaction (by EV or CSMS)
OperationModeChanged 2.1 only Operation mode of the transaction changed
RunningCost 2.1 only Running cost update sent by the CS
SoCLimitReached 2.1 only State of Charge limit was reached
TariffChanged 2.1 only The tariff applied to the transaction changed
TariffNotAccepted 2.1 only EV did not accept the tariff
TxResumed 2.1 only Transaction resumed after an interruption (reboot/power loss)

All existing 2.0.1 values remain unchanged: Authorized, CablePluggedIn, ChargingRateChanged, ChargingStateChanged, Deauthorized, EnergyLimitReached, EVCommunicationLost, EVConnectTimeout, EVDetected, EVDeparted, MeterValueClock, MeterValuePeriodic, TimeLimitReached, Trigger, UnlockCommand, StopAuthorized, RemoteStop, RemoteStart, AbnormalCondition, SignedDataReceived, ResetCommand.

Action Required: Add handling for all new trigger reasons in your TransactionEventRequest handler. CostLimitReached, LimitSet, SoCLimitReached are essential for E16. TxResumed is essential for E17. TariffChanged, TariffNotAccepted, RunningCost support the new tariff and cost features.

2.5 ReasonEnumType (stoppedReason) — New Value

Value Version Description
ReqEnergyTransferRejected 2.1 only Requested energy transfer type was not granted

All existing 2.0.1 values remain unchanged: DeAuthorized, EmergencyStop, EnergyLimitReached, EVDisconnected, GroundFault, ImmediateReset, Local, LocalOutOfCredit, MasterPass, Other, OvercurrentFault, PowerLoss, PowerQuality, Reboot, Remote, SOCLimitReached, StoppedByEV, TimeLimitReached, Timeout.

Action Required: Add ReqEnergyTransferRejected to your stoppedReason handling and billing logic.

3. Use Case Changes (E01–E15)

E01 — Start Transaction Options No Change

No functional changes. The core logic remains the same. The CSMS must validate IdTokens and respond with idTokenInfo. Schema changes (new optional fields in request/response) apply as documented in Section 2.

E02 — Start Transaction: Cable Plugin First Updated

Connector status notification changed

Step OCPP 2.0.1 OCPP 2.1
Cable plugged in StatusNotificationRequest(connectorStatus = Occupied) NotifyEventRequest(component.name = "Connector", variable.name = "AvailabilityState", actualValue = "Occupied")
Response StatusNotificationResponse {} NotifyEventResponse {}

The core transaction flow (TransactionEventRequest Started → Updated with Authorized → Updated with ChargingStateChanged) remains the same.

New functional requirements in 2.1

E02.FR.09

Meter values in Started event have context = Transaction.Begin (was implicit, now explicit)

E02.FR.10

Meter values in Updated events are periodic readings (was implicit, now explicit)

E02.FR.11

CS may split large meter data across multiple Updated messages with same timestamp (new clarification)

E03 — Start Transaction: IdToken First Updated

Connector status notification changed (same as E02 — see Section 5). No other functional changes. EVConnectTimeout handling remains the same.

E04 — Offline Start Transaction No Change

No functional changes. The offline = true flag behavior and retroactive processing remain the same.

E05 — Start Transaction: Id Not Accepted Clarified

E05.FR.09

Explicitly states that when StopTxOnInvalidId = true, CS stops energy transfer and sends Deauthorized trigger (was implied in 2.0.1, now explicit).

No other functional changes. The CSMS behavior is the same.

E06 — Stop Transaction Options No Change

No functional changes. All stop triggers and CSMS responsibilities remain the same.

E07 — Transaction Locally Stopped by IdToken Clarified

E07.FR.06

Added explicit statement that if the transaction is stopped NOT on driver request, CS uses the appropriate ReasonEnumType value (was implied in 2.0.1).

The two-variant flow (direct Ended vs Update-then-Ended based on TxStopPoint) remains the same.

E08 — Transaction Stopped While Offline No Change

No functional changes. Offline stop handling remains the same.

E09 — Cable Disconnected on EV-side: Stop Transaction Updated

Connector status notification changed

Step OCPP 2.0.1 OCPP 2.1
Connector available StatusNotificationRequest(status = Available) NotifyEventRequest(component.name = "Connector", variable.name = "AvailabilityState", actualValue = "Available")
Response StatusNotificationResponse {} NotifyEventResponse {}

No other functional changes.

E10 — Cable Disconnected on EV-side: Suspend Transaction New Scenario

In OCPP 2.0.1, only two outcomes were documented: cable plugged back in (resume) or driver authorizes stop. OCPP 2.1 adds a third option:

Option C (NEW in 2.1): Timeout — permanently attached cable
// Option C (NEW in 2.1): Timeout (cable permanently attached)
[Receive] TransactionEventRequest
    eventType = Ended,
    stoppedReason = Timeout,
    transactionId = "AB1234"
[Send]    TransactionEventResponse { ... }

Action Required: Handle stoppedReason = Timeout as a valid transaction end for suspended transactions with permanently attached cables.

E11 — Connection Loss During Transaction Clarified

E11.FR.05

When the CS runs low on memory, it drops intermediate messages first (2nd, 4th, 6th, etc.), never the first or last message of a transaction.

This was not specified in 2.0.1. The CSMS should expect sequence number gaps following this pattern when processing offline messages.

Action Required: Update sequence number gap detection logic to account for the intermediate-first dropping pattern.

E12 — Inform CSMS of Offline Occurred Transaction Clarified

E12.FR.04

When the CS drops non-critical Updated messages due to low memory, it SHALL NOT drop messages with these triggerReason values:

LimitSetCostLimitReachedEnergyLimitReachedTimeLimitReachedSoCLimitReached
E12.FR.05

Same intermediate-first dropping pattern as E11.FR.05.

Action Required: Be aware that limit-related trigger reasons are guaranteed to be present even when other intermediate messages are dropped.

E13 — Transaction-related Message Not Accepted by CSMS Clarified

OCPP 2.1 explicitly documents the retry behavior with specific configuration variables:

Variable Description
MessageAttemptsTransactionEvent Max number of retry attempts
MessageAttemptIntervalTransactionEvent Base interval between retries (seconds)

Retry algorithm New in 2.1

1st failure: wait interval × 1, resend

2nd failure: wait interval × 2, resend

Nth failure: wait interval × N, resend

After MessageAttemptsTransactionEvent failures: discard message

This was not explicitly documented in 2.0.1. No CSMS code changes needed, but understanding the retry pattern helps with timeout and duplicate handling.

E15 — End of Charging Process Scope Narrowed

Aspect OCPP 2.0.1 OCPP 2.1
Scope General "End of Charging Process" covering multiple interruption methods, remote stop, availability changes, and a full finalization checklist Specifically covers ISO 15118 SessionStopReq(Terminate) flow
Interruption methods Documented: ChangeAvailability, authorization revocation, RemoteStop Not covered in E15 (moved to relevant sections)
Finalization checklist Included in E15 Not included in E15

Key 2.1 E15 behavior

E15.FR.04

When TxStopPoint contains Authorized/PowerPathClosed/EnergyTransfer, CS sends eventType = Ended with triggerReason = StopAuthorized and stoppedReason = StoppedByEV.

E15.FR.05

When TxStopPoint does NOT contain those values, CS sends eventType = Updated with triggerReason = StopAuthorized (transaction continues until TxStopPoint condition met).

No CSMS logic changes needed — the messages received are the same. The finalization checklist from 2.0.1 E15 is still valid practice, just not in E15 scope anymore.

4. New Use Cases in 2.1 (E16–E17)

E16 — Transactions with Limits New

This is an entirely new use case in OCPP 2.1. It enables both the EV Driver and the CSMS to set limits on a transaction.

Limit Types

Limit Type Field Unit Description
Cost maxCost tariff currency Maximum allowed cost
Energy maxEnergy Wh Maximum energy to deliver
Time maxTime seconds Maximum transaction duration
State of Charge maxSoC % (0–100) Maximum battery SoC

Who Can Set Limits

Source How Message
EV Driver (via EV) ISO 15118 communication CS sends TransactionEventRequest(triggerReason = LimitSet, transactionInfo.transactionLimit = { ... })
CSMS Response to any TransactionEventRequest CSMS includes transactionLimit in TransactionEventResponse

CSMS Setting a Limit

CSMS sets limit → CS confirms
// CSMS responds to any TransactionEventRequest with:
{
  "idTokenInfo": { "status": "Accepted" },
  "transactionLimit": {
    "maxCost": 25.00
  }
}

// CS confirms the limit in the next TransactionEventRequest:
// triggerReason = "LimitSet"
// transactionInfo.transactionLimit = { "maxCost": 25.00 }

When a Limit is Reached

The CS sends a TransactionEventRequest with:

triggerReason = CostLimitReached / EnergyLimitReached / TimeLimitReached / SoCLimitReached

If TxStopPoint is NOT EnergyTransfer: eventType = Updated, chargingState = SuspendedEVSE

If TxStopPoint is EnergyTransfer: eventType = Ended

Key Requirements

Req ID Requirement
E16.FR.02 CSMS sets limits via transactionLimit in TransactionEventResponse
E16.FR.03 CS confirms limits by echoing them back in TransactionEventRequest
E16.FR.04 CS SHALL NOT exceed CSMS-set limits
E16.FR.07 CSMS can update limits by sending new values
E16.FR.11 When maxCost is active, CSMS SHALL provide cost updates via totalCost in responses
E16.FR.12 CSMS SHALL NOT send limit types not reported in TxCtrlr.SupportedLimits
E16.FR.14 If limit is increased after SuspendedEVSE, CS resumes charging
E16.FR.17 To remove a limit, set it to a very high value (limits cannot be unset)
E16.FR.18 Don't expect limit confirmation for offline messages

Action Required: Check TxCtrlr.SupportedLimits before sending any transactionLimit in responses. Implement logic to set, update, and track limits on active transactions. When maxCost is active, provide running cost updates via totalCost in TransactionEventResponse. Handle limit-reached trigger reasons. Store confirmed limits echoed back by the CS.

E17 — Resuming Transaction After Forced Reboot New

This is an entirely new use case in OCPP 2.1. It handles the scenario where a Charging Station reboots unexpectedly (power loss, software fault) and can resume transactions.

A new configuration variable TxResumptionTimeout controls how long after a reboot the CS will attempt to resume a transaction. If the interruption is within this timeout, the transaction resumes. If exceeded, the transaction ends.

Scenario 1: Resume Within Timeout

Transaction resumed after reboot
[Receive] TransactionEventRequest
    eventType = Updated,
    triggerReason = TxResumed,           // NEW trigger reason
    transactionId = "AB1234",
    transactionInfo: {
        chargingState: <state before interruption>
    }
[Send]    TransactionEventResponse { ... }

Scenario 2: End After Timeout Exceeded

Transaction ended — timeout exceeded
[Receive] TransactionEventRequest
    eventType = Ended,
    triggerReason = AbnormalCondition,
    transactionId = "AB1234",
    stoppedReason = PowerLoss            // or Reboot
[Send]    TransactionEventResponse { ... }

Key Requirements

Req ID Requirement
E17.FR.14 CS sends eventType = Updated, triggerReason = TxResumed with chargingState
E17.FR.15 CSMS SHALL resend SetChargingProfileRequest for TxProfile charging profiles when ChargingProfilePersistence for TxProfile is false or absent
E17.FR.21 If timeout exceeded due to power loss: stoppedReason = PowerLoss
E17.FR.22 If timeout exceeded due to software fault: stoppedReason = Reboot

Action Required: Handle triggerReason = TxResumed in your TransactionEventRequest handler. After receiving TxResumed, check if you have a TxProfile charging profile for this transaction and whether it persists across reboots — if not, resend it via SetChargingProfileRequest. Handle stoppedReason = PowerLoss and stoppedReason = Reboot for transactions that could not be resumed. Store wasInterrupted flag on transactions for analytics/billing purposes.

5. Connector Status Notification Change

This is a cross-cutting change that affects E02, E03, E09, and any other flow that reports connector/EVSE availability.

Aspect OCPP 2.0.1 OCPP 2.1
Message StatusNotificationRequest NotifyEventRequest
Response StatusNotificationResponse NotifyEventResponse
Data model connectorStatus field Component/Variable pattern

Example

OCPP 2.0.1
CS -> CSMS: StatusNotificationRequest(
    connectorStatus = "Occupied"
)
CSMS -> CS: StatusNotificationResponse {}
OCPP 2.1
CS -> CSMS: NotifyEventRequest(
    component.name = "Connector",
    variable.name = "AvailabilityState",
    actualValue = "Occupied"
)
CSMS -> CS: NotifyEventResponse {}

Action Required: If your CSMS handles StatusNotificationRequest for connector state during transaction flows, migrate to handling NotifyEventRequest with the Component/Variable pattern. The connector status values remain conceptually the same (Occupied, Available, etc.).

6. Configuration Variable Changes

New Configuration Variables in 2.1

Variable Component Description
TxResumptionTimeout TxCtrlr Time (seconds) after reboot within which CS attempts to resume transactions (E17)
SupportedLimits TxCtrlr List of supported limit types: maxEnergy, maxCost, maxTime, maxSoC (E16)
ChargingProfilePersistence TxCtrlr Whether charging profiles persist across reboots (affects E17.FR.15)
MessageAttemptsTransactionEvent OCPPCommCtrlr Max retry attempts for TransactionEventRequest (E13)
MessageAttemptIntervalTransactionEvent OCPPCommCtrlr Base interval between retries in seconds (E13)

Unchanged Configuration Variables

Variable Component Description
TxStartPoint TxCtrlr Defines when transaction starts
TxStopPoint TxCtrlr Defines when transaction ends
StopTxOnInvalidId TxCtrlr Whether to stop tx when Id becomes invalid
MaxEnergyOnInvalidId TxCtrlr Max Wh to deliver with invalid Id
StopTxOnEVSideDisconnect TxCtrlr Stop tx when cable disconnected at EV side
UnlockOnEVSideDisconnect TxCtrlr Unlock connector when cable disconnected at EV side
EVConnectionTimeOut TxCtrlr Timeout for EV to connect after authorization
AuthorizeRemoteStart AuthCtrlr Whether to authorize remote start transactions
MasterPassGroupId AuthCtrlr GroupId for Master Pass tokens

7. Migration Checklist

Must Do Breaking / Functional

E02/E03/E09

Handle NotifyEventRequest instead of StatusNotificationRequest for connector state changes during transaction flows.

TriggerReason

Add all new TriggerReasonEnumType values to your TransactionEventRequest handler: CostLimitReached, LimitSet, OperationModeChanged, RunningCost, SoCLimitReached, TariffChanged, TariffNotAccepted, TxResumed.

stoppedReason

Add ReqEnergyTransferRejected to your stoppedReason handling.

E17

Handle triggerReason = TxResumed for transaction resumption after reboot.

Should Do New Capabilities

E16

Implement transactionLimit in TransactionEventResponse to set/update limits.

E16

Handle limit-reached trigger reasons and track confirmed limits from CS.

E16

Check TxCtrlr.SupportedLimits before sending transactionLimit.

E16

Send totalCost as running cost in Updated responses when maxCost limit is active.

E17

Resend TxProfile charging profiles via SetChargingProfileRequest after transaction resume when profiles are not persisted (E17.FR.15).

E10

Handle stoppedReason = Timeout for suspended transactions with permanently attached cables.

Nice to Have Optional Enhancements

Store preconditioningStatus for battery conditioning analytics.

Store evseSleep for EVSE power state tracking.

Store costDetails from CS and compare with CSMS-calculated costs.

Store operationMode and tariffId from transactionInfo.

Send updatedPersonalMessageExtra for multi-message display scenarios.

Update sequence gap detection to account for intermediate-first message dropping (E11.FR.05).

Track non-droppable trigger reasons when processing offline transaction batches (E12.FR.04).

Data Model Updates

Add the following fields to your Transaction data model:

Data model additions
Transaction (existing model):
+   tariffId: string (max 60, nullable)              // NEW
+   transactionLimits: TransactionLimitType (nullable) // NEW
+   costDetails: CostDetailsType (nullable)            // NEW
+   wasInterrupted: boolean (default false)            // NEW (for E17 tracking)

TransactionEvent (existing model):
+   preconditioningStatus: enum (nullable)             // NEW
+   evseSleep: boolean (nullable)                      // NEW

OCPP 2.1 Transactions Section Migration Guide — Use Cases E01–E17 — CSMS Developer Perspective