Link copied

Purpose: Practical reference for AI agents implementing or debugging the OCPP 2.1 additions to smart charging. Covers ONLY what is new versus 2.0.1: dynamic charging profiles / dynamic schedules, priority charging, battery swap, and periodic event streams. Shared fundamentals (the charging-profile model, stack levels, composite schedule) are unchanged — this document cross-links the 2.0.1 deep-dive rather than repeating them.

Last updated: 2026-06-11


#How This Document Was Produced

This document covers the OCPP 2.1 smart-charging additions relative to 2.0.1. Its dominant confidence tier is spec-knowledge — behavioral rules summarized in original wording from the OCPP 2.1 Edition 2 Part 2 specification (Smart Charging block K, especially use cases K15–K29). All message names, field names, and enum values are schema-derived — cross-referenced against the mechanically generated SmartCharging schema doc, BatterySwap schema doc, Diagnostics schema doc, and the Data Types reference, all extracted from the official OCA artifacts. No spec prose is reproduced verbatim (the OCA specification is CC BY-ND licensed); all explanatory text is original.

This document contains 3 escalation points marked with > **ESCALATE:**. When an AI agent encounters one, it MUST stop and ask the developer (or operator) to make the decision. See METHODOLOGY.md for the confidence and escalation model.

Companion documents:


#1. What Is New in 2.1

The 2.0.1 charging-profile model is carried forward unchanged: SetChargingProfile, GetChargingProfiles, ClearChargingProfile, ReportChargingProfiles, GetCompositeSchedule, NotifyChargingLimit, ClearedChargingLimit, NotifyEVChargingNeeds, NotifyEVChargingSchedule all behave as documented in the 2.0.1 deep-dive. OCPP 2.1 adds the following on top:

Area New messages Purpose
Dynamic charging profiles UpdateDynamicSchedule (CSMS → CS), PullDynamicScheduleUpdate (CS → CSMS) Update the limits/setpoints of an existing dynamic profile without re-installing the whole profile.
Priority charging UsePriorityCharging (CSMS → CS), NotifyPriorityCharging (CS → CSMS) Temporarily charge one transaction at maximum priority (e.g. an EV that must leave soon).
Battery swap RequestBatterySwap (CSMS → CS), BatterySwap (CS → CSMS) Coordinate physical battery exchange at a swap station.
Periodic event streams OpenPeriodicEventStream, ClosePeriodicEventStream (CS → CSMS), GetPeriodicEventStream, AdjustPeriodicEventStream (CSMS → CS), NotifyPeriodicEventStream (CS → CSMS, one-way) Efficient high-rate telemetry without per-sample request/response overhead.

New enum values added to the carried-over charging types:

Type New 2.1 value Meaning
ChargingProfileKindEnumType Dynamic The schedule periods carry live setpoints/limits that the CSMS (or the CS, by pull) updates over time.
ChargingProfilePurposeEnumType PriorityCharging Profile purpose dedicated to priority charging.
ChargingProfilePurposeEnumType LocalGeneration Profile representing locally generated capacity (e.g. on-site PV) rather than a limit.

#2. Dynamic Charging Profiles / Dynamic Schedules

#2.1 Concept

A dynamic charging profile is a charging profile whose chargingProfileKind is the Dynamic value of ChargingProfileKindEnumType. Unlike Absolute / Recurring / Relative profiles — whose schedule periods are fixed at install time — a dynamic profile's per-period limits and setpoints are expected to change during the transaction. The CSMS pushes new values, or the CS pulls them, without resending the full SetChargingProfile payload each time.

This is the OCPP-level mechanism behind ISO 15118-20 dynamic control mode (see ControlModeEnumType DynamicControl reported in NotifyEVChargingNeeds) and behind V2X setpoint following (cross-link the Bidirectional / V2X doc).

#2.2 Dynamic fields on a charging schedule period

These (2.1) fields on ChargingSchedulePeriodType make dynamic operation possible. They are also the fields the update messages (§2.3) can change.

Field Meaning
setpoint Target the EV should follow as closely as possible (negative = discharge). setpoint_L2, setpoint_L3 for per-phase.
setpointReactive Reactive-power/current target (positive = inductive, negative = capacitive). setpointReactive_L2, setpointReactive_L3 per phase.
dischargeLimit Maximum the EV may discharge (a negative value; max: 0.0). dischargeLimit_L2, dischargeLimit_L3 per phase.
limit / limit_L2 / limit_L3 Charging-rate ceiling (carried over, now optional depending on operation mode).
v2xBaseline Baseline power onto which the V2X curves are added.
v2xFreqWattCurve V2XFreqWattPointType[] — frequency→watt response curve. See V2X doc.
v2xSignalWattCurve V2XSignalWattPointType[] — signal→watt response curve. See V2X doc.

Two (2.1) fields on ChargingProfileType coordinate the update cadence:

Field Meaning
dynUpdateInterval Seconds after the last update at which the CS should request a fresh one via PullDynamicScheduleUpdate. 0 or absent = no pull interval. Only relevant for a dynamic profile.
dynUpdateTime Timestamp at which the limits/setpoints were last updated (by a pull, a push, or an external actor). Only relevant for a dynamic profile.

#2.3 The two update messages

Both messages address an existing profile by chargingProfileId and carry a ChargingScheduleUpdateType — a subset of the period containing only the changeable fields (limit*, setpoint*, setpointReactive*, dischargeLimit*). They do not install or replace a profile.

Message Direction Request key fields Response Notes
UpdateDynamicSchedule CSMS → CS chargingProfileId, scheduleUpdate (required) status: ChargingProfileStatusEnumType (Accepted / Rejected) CSMS pushes new setpoints/limits into the live dynamic profile.
PullDynamicScheduleUpdate CS → CSMS chargingProfileId status: ChargingProfileStatusEnumType; optional scheduleUpdate CS asks the CSMS for the latest values (e.g. when offline-buffered or on dynUpdateInterval). The CSMS returns the update in the response.

The full establish-then-update loop is in the Sequences doc §2.

ESCALATE: POLICY-DEPENDENT — Whether your CSMS drives a dynamic profile by push (UpdateDynamicSchedule on the CSMS's own cadence) or relies on the CS to pull (dynUpdateInterval + PullDynamicScheduleUpdate), and how often, depends on your control strategy, the EV/charger capability, and grid-signal latency. Confirm the intended mode with the operator.


#3. Priority Charging

#3.1 Concept

Priority charging lets the CSMS (or a local action relayed by the CS) temporarily promote one transaction to charge at maximum allowed rate, overriding the normal smart-charging limits applied to it. Typical uses: a driver who pays for or requests a "boost", or an operational need to free a bay quickly. The dedicated PriorityCharging value of ChargingProfilePurposeEnumType marks the profile that backs it.

#3.2 Messages

Message Direction Request key fields Response Notes
UsePriorityCharging CSMS → CS activate (boolean), transactionId status: PriorityChargingStatusEnumType (Accepted / Rejected / NoProfile) CSMS requests starting (true) or stopping (false) priority charging for a transaction. NoProfile means no priority-charging profile is configured.
NotifyPriorityCharging CS → CSMS activated (boolean), transactionId empty {} CS reports that priority charging actually started (true) or stopped (false) for the transaction — e.g. after a local trigger or when the priority profile ends.

ESCALATE: POLICY-DEPENDENT — Eligibility for priority charging (who may invoke it, pricing, and the rate it grants relative to grid/site ceilings) is an operator business decision. Do not hard-code an answer.


#4. Battery Swap

OCPP 2.1 adds coordination for battery-swap stations, where a depleted pack is physically exchanged rather than charged in place (block S, use cases S01–S04).

Message Direction Request key fields Response Notes
RequestBatterySwap CSMS → CS idToken, requestId status: GenericStatusEnumType CSMS asks the station to begin a swap for an authorized token.
BatterySwap CS → CSMS batteryData[], eventType, idToken, requestId empty {} CS notifies battery in/out events. eventType is BatterySwapEventEnumType: BatteryIn / BatteryOut / BatteryOutTimeout. requestId correlates the events (and the optional RequestBatterySwap).

The full flow is in the Sequences doc §3.


#5. Periodic Event Streams

#5.1 Concept

A periodic event stream is an efficient transport for high-rate telemetry. Instead of one request/response pair per sample (as with polled GetVariables or per-event NotifyEvent), the CS opens a stream tied to a monitor and then pushes batches of timestamped values in one-way NotifyPeriodicEventStream messages. This removes per-sample round-trip overhead (block N, use cases N11–N15).

A stream is bound to a variableMonitoringId via ConstantStreamDataType and paced by PeriodicEventStreamParamsType (interval seconds, values items per send).

#5.2 The five messages (N11–N15)

Message Direction Purpose
OpenPeriodicEventStream CS → CSMS CS opens a stream (constantStreamData); CSMS replies Accepted/Rejected.
NotifyPeriodicEventStream CS → CSMS (one-way SEND) CS pushes a batch: basetime, data[] (StreamDataElementType with offset t + value v), stream id, and pending count. No response.
AdjustPeriodicEventStream CSMS → CS CSMS re-paces an existing stream (id, params).
GetPeriodicEventStream CSMS → CS CSMS requests the list of currently configured streams.
ClosePeriodicEventStream CS → CSMS CS closes a stream by id.

ESCALATE: POLICY-DEPENDENT — Stream rate (interval / values) and which variables warrant streaming versus polling are a bandwidth/cost trade-off specific to the deployment and back-end ingestion capacity. Confirm targets with the operator.

The full lifecycle is in the Sequences doc §5.