Link copied

Purpose: Practical reference for AI agents implementing or debugging OCPP 2.1 bidirectional power transfer (V2X). Covers what V2X is, the operation-mode model, setpoints and charge/discharge limits, mode switching and entry/exit flows, frequency support (FCR / aFRR), allowed-energy-transfer negotiation, and offline behavior. Functional Block Q.

Last updated: 2026-06-09


#How This Document Was Produced

This document covers OCPP 2.1 Functional Block Q (Bidirectional Power Transfer / V2X). Its dominant confidence tier is spec-knowledge — behavioral rules summarized from the OCPP 2.1 Edition 2 Part 2 specification, section Q (use cases Q01–Q12). All message names, field names, and enum values are schema-derived: cross-referenced against the mechanically generated Bidirectional schema doc, the SmartCharging schema doc, and the Data Types reference. Where a behavior depends on grid-operator, market, or vendor policy, it is marked as an escalation point rather than asserted.

This document contains 5 escalation points marked with > **ESCALATE: POLICY-DEPENDENT**. When an AI agent encounters one, it MUST stop and ask the developer/operator to make the decision. See METHODOLOGY.md for the full confidence and escalation model.

Companion documents:


#1. What V2X Is and Why 2.1 Adds It

Bidirectional power transfer lets an EV not only draw power from the grid but also export power back. OCPP 2.1 introduces this as Functional Block Q. The spec uses the umbrella term V2X ("vehicle-to-anything") rather than V2G, to avoid colliding with ISO 15118's own use of "V2G" for the EV↔Charging-Station link.

V2X variants (all handled identically in OCPP — only the destination of the exported power differs):

Term Meaning
V2G Vehicle-to-grid: export power to the electricity grid
V2H Vehicle-to-home: power a home, e.g. during a grid outage or to avoid grid draw
V2B Vehicle-to-building: power a building, same idea at building scale
V2L Vehicle-to-load: power an appliance directly — out of scope for OCPP, no CSMS involvement

Why it was added: a parked EV is a large battery. Letting it discharge enables grid balancing services (frequency reserves), local load balancing against on-site generation (e.g. solar), backup power, and energy arbitrage — turning charging infrastructure into a flexible grid resource.

#Relationship to ISO 15118-20

V2X over OCPP requires a bidirectional-capable EV-to-station protocol. The spec defines Block Q for use when the EV↔station link is ISO 15118-20 or CHAdeMO. ISO 15118-20 carries the service negotiation (the EV and station agree on a bidirectional energy-transfer service); OCPP carries the authorization of that service and the control loop (setpoints/limits) between station and CSMS. Prerequisite control variables: ISO15118Ctrlr.Enabled = true and V2XChargingCtrlr.Enabled = true.

#Block Q Messages

Only two messages are unique to Block Q. V2X control itself reuses the Smart Charging (Block K) machinery.

Message Direction Purpose
NotifyAllowedEnergyTransfer CSMS → CS Tell the CS which energy-transfer modes are allowed for a transaction (see §6)
AFRRSignal CSMS → CS Push an aFRR activation signal value to the CS (see §5)

V2X control is expressed through charging profiles delivered by SetChargingProfile and updated by UpdateDynamicSchedule / PullDynamicScheduleUpdate. The allowed transfer modes are negotiated via NotifyEVChargingNeeds. This document cross-links those rather than duplicating their schemas.


#2. V2X Operation Modes

The mode of operation for each schedule interval is set by the operationMode field of ChargingSchedulePeriodType. The enum is OperationModeEnumType. When operationMode is absent it defaults to ChargingOnly.

The eight values (the first four are shared with regular smart charging; the others are V2X-specific):

operationMode value Who determines the control value Bidirectional? Notes
ChargingOnly CS follows limit only No Default. Charge-only; used as a safe starting mode before V2X is authorized. setpoint/dischargeLimit not used.
ExternalSetpoint External actor (e.g. EMS) sets the setpoint Yes (setpoint may be negative) CSMS may still bound it with limit and dischargeLimit.
ExternalLimits External actor sets limit and dischargeLimit Yes Like ExternalSetpoint but the limits, not the setpoint, are externally driven.
CentralSetpoint CSMS sets setpoint in the schedule period Yes (negative = discharge) With chargingProfileKind = Dynamic, CSMS updates setpoint via UpdateDynamicSchedule without resending the profile. limit/dischargeLimit are not the control signal (setpoint is); optional bounding still applies.
CentralFrequency CSMS computes setpoint from centrally measured frequency Yes For calibrated frequency metering done centrally. Requires chargingProfileKind = Dynamic; CSMS pushes new setpoints continually. If no update arrives in time, the profile terminates and the CS falls back to a lower stack level.
LocalFrequency CS computes setpoint locally from a frequency-watt curve Yes FCR / aFRR participation. Requires chargingRateUnit = W. Uses v2xFreqWattCurve (FCR) and/or v2xSignalWattCurve + AFRRSignal (aFRR). See §5.
LocalLoadBalancing CS computes setpoint locally from a metered building load Yes EV compensates building load (e.g. against solar). Controlled by configuration keys UpperThreshold, LowerThreshold, UpperOffset, LowerOffset (require UpperThreshold > LowerThreshold).
Idle Neither charge nor discharge No (suspended) EV refrains from charging/discharging for the interval. limit, dischargeLimit, setpoint, setpointReactive MUST be absent. Optional battery preconditioning (preconditioningRequest) and EVSE sleep (evseSleep) — see §7.

ESCALATE: POLICY-DEPENDENT — Which operation modes to enable for a given site or EV is an operator/market decision. Discharging modes may require third-party (eMSP / aggregator / grid-operator) authorization, contracts, or grid-code compliance. Do not enable *Setpoint, *Frequency, or LocalLoadBalancing modes by default; confirm the operator's V2X service policy first.


#3. Setpoints and Charge/Discharge Limits

V2X reuses the charging-profile model but extends ChargingSchedulePeriodType with bidirectional fields. All values are in the schedule's chargingRateUnit (Watts or Amperes).

Field Sign convention Meaning
setpoint Positive = charge, negative = discharge Target rate the EV should follow as closely as possible.
limit Positive only Maximum allowed charging rate.
dischargeLimit Negative only (schema constraint max: 0.0) Maximum allowed discharging rate (a floor, since it is negative).
setpointReactive Positive = inductive, negative = capacitive Reactive-power (or current) setpoint.

Phase-specific variants exist for AC: setpoint_L2 / setpoint_L3, limit_L2 / limit_L3, dischargeLimit_L2 / dischargeLimit_L3, setpointReactive_L2 / setpointReactive_L3. When the L2/L3 fields are present, the un-suffixed field represents L1; otherwise it represents the sum of all phases.

When a setpoint is given together with limit and/or dischargeLimit, any overshoot while tracking the setpoint must stay within those bounds. Which fields are required vs. ignored depends on operationMode (see the per-mode notes in §2).

Frequency-support curve fields (used by the frequency modes, §5):

Field Type Meaning
v2xFreqWattCurve V2XFreqWattPointType[] (1–20 points) Power/frequency (FCR) curve: each point is {frequency (Hz), power (W; +charge / −discharge)}. Values between points are linearly interpolated.
v2xSignalWattCurve V2XSignalWattPointType[] (1–20 points) Signal/watt (aFRR) curve: each point is {signal (integer), power (W)}. Maps an AFRRSignal.signal value to a power level.
v2xBaseline number Baseline power on top of which v2xFreqWattCurve / v2xSignalWattCurve outputs are added.

Note: the JSON schema accepts a single point (minItems: 1), but a one-point curve yields a fixed output independent of frequency/signal — no interpolation is possible. The spec prose expects at least two points for a meaningful curve.

For the full charging-profile structure, stack-level priority, and chargingProfileKind (Absolute / Recurring / Relative / Dynamic), see the SmartCharging schema doc. V2X does not change those mechanics; it only adds the fields above and the V2X operationMode values.

ESCALATE: POLICY-DEPENDENT — Concrete discharge-limit values (dischargeLimit) and the maximum export power for a site depend on the grid connection capacity, the EV/battery warranty terms, and any local export agreement. These must come from the operator/grid configuration, not be inferred.


#4. Switching Modes / Entering and Leaving V2X

#4.1 Authorizing and entering V2X (Q01)

Because a V2X energy service often needs third-party authorization that may not complete within the EV's ISO 15118-20 timeout, the recommended pattern is to start in ChargingOnly and renegotiate to V2X once the allowed transfer modes are known (see §4.2). Direct entry (Q01) when V2X is pre-authorized:

Step Sender → Receiver Message Trigger / Notes
1 CS → CSMS Authorize EV plugged in; CS includes the ISO 15118 EVCCID in idToken.additionalInfo.
2 CSMS → CS Authorize (response) idTokenInfo.status = Accepted, plus the allowedEnergyTransfer list for this EV.
3 CS → CSMS TransactionEvent (eventType = Started) Transaction begins.
4 (ISO 15118-20 service negotiation) EV and CS agree on an energy-transfer method.
5 CS → CSMS NotifyEVChargingNeeds Carries the chosen requestedEnergyTransfer (and optional availableEnergyTransfer list), departureTime, and control mode.
6 CSMS → CS NotifyEVChargingNeeds (response) status = Accepted (a SetChargingProfile will follow) or NoChargingProfile (CS should use its TxDefaultProfile).
7 CSMS → CS SetChargingProfile Profile whose schedule has a V2X operationMode (anything other than ChargingOnly). Skipped if step 6 returned NoChargingProfile.
8 (CS → EV) CS relays charge/discharge parameters to EV; EV requests V2X power transfer; CS accepts. V2X operation active.

Error handling (Q01): if the CSMS does not accept the requestedEnergyTransfer, it responds to NotifyEVChargingNeeds with status = Rejected and the CS stops the transaction.

#4.2 Safe-start then enable V2X (Q02)

Step Sender → Receiver Message Trigger / Notes
1 CSMS → CS SetChargingProfile Schedule with operationMode = ChargingOnly — transaction starts charge-only while V2X authorization is pending.
2 CSMS → CS NotifyAllowedEnergyTransfer Once a V2X mode is authorized, CSMS updates the allowed list for the EVSE/transaction (includes a V2X EnergyTransferModeEnumType, e.g. DC_BPT).
3 CS → CSMS NotifyAllowedEnergyTransfer (response) status = Accepted.
4 (ISO 15118-20 service renegotiation) EV/CS renegotiate to the V2X service.
5 CSMS → CS SetChargingProfile New/updated profile with a V2X operationMode; bidirectional operation begins.

#4.3 Leaving / falling back

A mode change is just a new schedule period or a higher-priority profile expiring. Two key fallbacks:


#5. Frequency Support — FCR and aFRR

Two grid-balancing products are supported, both through frequency-related operation modes. Both require chargingRateUnit = W.

#5.1 FCR (Frequency Containment Reserve), via LocalFrequency

FCR (primary control reserve) reacts automatically within seconds to grid frequency deviations. In OCPP the CS reads grid frequency locally and derives the power setpoint from a power/frequency curve carried in v2xFreqWattCurve. Power for frequencies between curve points is computed by linear interpolation. No per-tick OCPP message is needed once the curve is installed — control is fully local.

#5.2 aFRR (automatic Frequency Restoration Reserve)

aFRR is the secondary reserve; it gradually replaces FCR after ~30 s, must be fully available within 15 minutes once activated (typical TSO/market figures, e.g. ENTSO-E, not OCPP constants), and must track a new setpoint every few seconds (typical TSO/market requirements). Activation comes from the TSO to the operator (CSO), which forwards it to affected stations as an AFRRSignal.

AFRRSignal (CSMS → CS):

Field Type Meaning
signal integer A signal value; the CS maps it to a power level via the v2xSignalWattCurve in the active schedule period.
timestamp date-time The moment the signal becomes active.

Response uses GenericStatusEnumType (Accepted / Rejected). The amount of upward/downward aFRR offered by a station is encoded in v2xSignalWattCurve (V2XSignalWattPointType[]): each point maps a signal integer to a power value.

Q07 vs Q08: CentralFrequency (Q07) has the CSMS compute and push the setpoint via UpdateDynamicSchedule (used when calibrated central metering is required); LocalFrequency (Q08) has the CS compute it locally from its curves. Note these V2X frequency modes are distinct from the frequency-droop / frequency-Watt features in Block R (DER Control) — in Block Q frequency support is the profile's primary goal, whereas in Block R it exists to satisfy grid-code requirements.

ESCALATE: POLICY-DEPENDENT — Participation in FCR/aFRR markets, the prequalified power offered, and the contents of v2xFreqWattCurve / v2xSignalWattCurve are commercial/grid-operator decisions (TSO contracts, prequalification). Do not synthesize curve values or enable frequency modes without the operator's market configuration.


#6. Allowed Energy Transfer

NotifyAllowedEnergyTransfer (CSMS → CS) tells the CS which energy-transfer modes are permitted for a specific transaction. It is sent when the set of allowed modes changes — typically after V2X authorization completes, or whenever an external/aggregating actor updates what this EV may do (the safe-start flow in §4.2).

Request fields:

Field Type Required Meaning
allowedEnergyTransfer EnergyTransferModeEnumType[] (minItems 1) Yes The modes the CSMS accepts for this transaction.
transactionId string (≤36) Yes The transaction the allowance applies to.

Response uses NotifyAllowedEnergyTransferStatusEnumType (Accepted / Rejected).

EnergyTransferModeEnumType values (the _BPT suffix denotes Bidirectional Power Transfer; _DER denotes DER-capable; _ACDP is automatic connection device / pantograph):

Value Bidirectional? Notes
AC_single_phase No Unidirectional AC, 1-phase
AC_two_phase No Unidirectional AC, 2-phase
AC_three_phase No Unidirectional AC, 3-phase
DC No Unidirectional DC
AC_BPT Yes Bidirectional AC
AC_BPT_DER Yes Bidirectional AC with DER capability
AC_DER No (DER) AC with DER capability
DC_BPT Yes Bidirectional DC
DC_ACDP No DC via automatic connection device (pantograph)
DC_ACDP_BPT Yes Bidirectional DC via automatic connection device
WPT No Wireless power transfer

The same enum also appears in Authorize (the allowedEnergyTransfer returned to the CS) and in NotifyEVChargingNeeds (requestedEnergyTransfer / availableEnergyTransfer), tying authorization, EV negotiation, and the standalone notify message together.

ESCALATE: POLICY-DEPENDENT — Which EnergyTransferModeEnumType values to place in allowedEnergyTransfer for a given EV/transaction is an authorization/market decision (per-EV contracts, aggregator rules, eMSP approval). Do not default to including _BPT modes; obtain the operator's allow-list logic.


#7. Idle Mode, Preconditioning, and EVSE Sleep (Q10)

operationMode = Idle requests the EV to neither charge nor discharge for the interval. The fields limit, dischargeLimit, setpoint, and setpointReactive (and their L2/L3 variants) MUST be absent; a SetChargingProfile that includes them with Idle is rejected with status = Rejected, statusInfo.reasonCode = "InvalidSchedule".

Two optional refinements on ChargingSchedulePeriodType during Idle:

Field Effect
preconditioningRequest If true, EV keeps the battery preconditioned (optimal temperature) for the interval — may draw some power.
evseSleep If true (and SmartChargingCtrlr.SupportsEvseSleep is true), the EVSE turns off the power electronics/modules for this transaction until an event requires reactivation (e.g. next period's mode change, a new profile including one with 0 W limits, or transaction stop). While sleeping, the CS reports evseSleep = true in TransactionEvent; any charging command — including a 0 W limit/setpoint — wakes it. If evseSleep is unsupported, the CS ignores it and reports evseSleep = false/absent.

#8. Offline V2X Behavior (Q11 / Q12)

Whether a V2X operation may continue while the CS is offline is governed by two fields on the profile (ChargingProfileType in Block K), not by anything Block-Q-specific:

Field Meaning
maxOfflineDuration How long (seconds) the profile stays valid after the CS detects it is offline. The countdown starts at the moment the CS detects the offline condition (expected within ~30 s).
invalidAfterOfflineDuration If true, once maxOfflineDuration has elapsed the profile is permanently invalid and is NOT reactivated when the CS comes back online.

#8.1 Going offline (Q11)

Step Actor Behavior
1 CS V2X operation active; CS loses connection to CSMS.
2 CS Detects offline; starts the maxOfflineDuration countdown.
3 CS While t ≤ maxOfflineDuration: continue the active V2X profile.
4 CS When t > maxOfflineDuration: profile becomes invalid; fall back to the next valid (lower stack-level) profile — which may itself be a V2X profile if its own maxOfflineDuration has not elapsed.
5 CS If there is no profile to fall back to, continue charging without a profile (charge-only, no limits).
6 CSMS On detecting the offline situation, assume the CS has reverted; do not try to compute the exact switch moment from maxOfflineDuration (CS and CSMS detect offline at different instants).

#8.2 Resuming after offline (Q12)

On reconnection the CS re-evaluates its profiles:

Case Condition Result on reconnect
1 t ≤ maxOfflineDuration V2X profile stayed active throughout; nothing changes.
2 t > maxOfflineDuration, invalidAfterOfflineDuration = false CS had fallen back to the lower (charge-only) profile while offline; on reconnect it re-selects the higher V2X profile and resumes V2X.
3 t > maxOfflineDuration, invalidAfterOfflineDuration = true The V2X profile is permanently ineligible; CS continues with the lower charge-only profile.

ESCALATE: POLICY-DEPENDENTmaxOfflineDuration and invalidAfterOfflineDuration for V2X profiles are risk/operational decisions: how long an EV may keep discharging without CSMS supervision, and whether stale V2X authorization may resume. Set these per the operator's offline-risk policy; do not pick defaults that allow unbounded offline discharge.


#9. Common Pitfalls (interpretation)