Smart Charging - CSMS Implementation Guide
Based on OCPP 2.0.1 Edition 4 Specification (Part 2, Section K). This guide covers all smart charging flows, profiles, and external limits from the CSMS perspective.
1. Overview
Concepts & BackgroundSmart Charging enables the CSO (or third party) to influence the charging current/power transferred during a transaction, or set limits on current/power a Charging Station can draw from the grid.
What is Smart Charging?
Internal Load Balancing
CS controls current/power per EVSE within its own fixed limit (e.g. grid connection max). No CSMS involvement during balancing.
Central Smart Charging
CSMS controls charging power/current per EV or entire CS. Based on grid capacity, energy prices, etc.
Local Smart Charging
A Local Controller manages a group of Charging Stations, distributing capacity among them.
External Smart Charging Control Signals
External systems (DSO, EMS, smart meter) set limits via non-OCPP protocols. CS reports these to CSMS.
Charging Profile Purposes
| Purpose | Description | evseId |
|---|---|---|
ChargingStationMaxProfile | Overall limit for the entire CS. Set at evseId=0 only. | 0 only |
TxDefaultProfile | Default schedule for new transactions. evseId=0 applies to all EVSEs. | 0 or >0 |
TxProfile | Transaction-specific profile. Overrules TxDefaultProfile. Must include transactionId. | >0 only |
ChargingStationExternalConstraints | Limits set by external systems (not CSMS). CSMS SHALL NOT set this purpose. | 0 or >0 |
Charging Profile Kind
| Kind | Description | startSchedule |
|---|---|---|
Absolute | Schedule periods relative to an absolute point in time. | Required |
Recurring | Schedule restarts periodically (Daily/Weekly). | Required |
Relative | Schedule starts when EVSE is ready to deliver energy (PowerPathClosed). | Must be absent |
Stacking & Combining Profiles
Stacking: Profiles of the same purpose can be stacked using stackLevel. Higher
stackLevel takes precedence.
Composite Schedule: The effective charging limit is the minimum of the leading profiles from each purpose (ChargingStationMaxProfile, ChargingStationExternalConstraints, TxDefaultProfile/TxProfile).
Priority: When both TxProfile and TxDefaultProfile exist, TxProfile always overrules TxDefaultProfile.
Note: It is NOT allowed to have multiple profiles with the same stackLevel + chargingProfilePurpose valid on the same EVSE at the same time.
2. Shared Data Types
Data StructuresChargingProfileType
{
"id": integer, // REQUIRED - Unique profile ID
"stackLevel": integer, // REQUIRED - Priority level (0 = lowest)
"chargingProfilePurpose": enum, // REQUIRED - See Purposes table
"chargingProfileKind": enum, // REQUIRED - "Absolute" | "Recurring" | "Relative"
"recurrencyKind": enum, // "Daily" | "Weekly" - Required only when kind=Recurring
"validFrom": date-time, // Optional - Profile valid from this time
"validTo": date-time, // Optional - Profile valid until this time
"chargingSchedule": [ChargingScheduleType], // REQUIRED - 1..3 schedules
"transactionId": string(36) // Only for TxProfile - matches to transaction
}ChargingScheduleType
{
"id": integer, // REQUIRED - Schedule identifier
"startSchedule": date-time, // Required for Absolute/Recurring, absent for Relative
"duration": integer, // Duration in seconds (omit for indefinite/until tx end)
"chargingRateUnit": "W" | "A", // REQUIRED
"chargingSchedulePeriod": [ChargingSchedulePeriodType], // REQUIRED - 1..1024 periods
"minChargingRate": number, // Optional - EV minimum efficient charging rate
"salesTariff": SalesTariffType // Optional - ISO 15118 sales tariff
}ChargingSchedulePeriodType
{
"startPeriod": integer, // REQUIRED - Offset in seconds from schedule start (first must be 0)
"limit": number, // REQUIRED - Rate limit in W or A (max 1 decimal, e.g. 8.1)
"numberPhases": integer, // Optional - Default 3
"phaseToUse": integer // Optional - 1..3, only when numberPhases=1 and ACPhaseSwitchingSupported
}ChargingLimitType
{
"chargingLimitSource": "EMS" | "Other" | "SO" | "CSO", // REQUIRED
"isGridCritical": boolean // Optional
}CompositeScheduleType
Returned in GetCompositeScheduleResponse - represents the effective charging schedule:
{
"evseId": integer, // REQUIRED
"duration": integer, // REQUIRED - seconds
"scheduleStart": date-time, // REQUIRED
"chargingRateUnit": "W" | "A", // REQUIRED
"chargingSchedulePeriod": [ChargingSchedulePeriodType] // REQUIRED
}3. Profile Management
K01, K08-K10K01 - SetChargingProfile
Set or update a charging profile on a Charging Station to influence charging power/current drawn from a specific EVSE or the entire CS over a period of time.
SetChargingProfileRequest
{
"evseId": integer, // REQUIRED - 0 = whole CS (for MaxProfile/ExternalConstraints/TxDefault)
"chargingProfile": { // REQUIRED - ChargingProfileType
"id": integer,
"stackLevel": integer,
"chargingProfilePurpose": "ChargingStationMaxProfile" | "TxDefaultProfile" | "TxProfile",
"chargingProfileKind": "Absolute" | "Recurring" | "Relative",
"recurrencyKind": "Daily" | "Weekly",
"validFrom": "2024-01-01T00:00:00Z",
"validTo": "2024-12-31T23:59:59Z",
"chargingSchedule": [{
"id": 1,
"startSchedule": "2024-01-01T00:00:00Z",
"duration": 86400,
"chargingRateUnit": "W",
"chargingSchedulePeriod": [
{ "startPeriod": 0, "limit": 11000, "numberPhases": 3 },
{ "startPeriod": 28800, "limit": 6000, "numberPhases": 3 },
{ "startPeriod": 72000, "limit": 11000, "numberPhases": 3 }
]
}],
"transactionId": "tx-uuid-here" // Only for TxProfile
}
}SetChargingProfileResponse
{
"status": "Accepted" | "Rejected",
"statusInfo": { // Optional
"reasonCode": "string",
"additionalInfo": "string"
}
}CSMS Implementation Rules
- • MUST NOT set chargingProfilePurpose to ChargingStationExternalConstraints
- • MUST include transactionId when setting a TxProfile
- • MUST NOT send overlapping profiles with same stackLevel + purpose + evseId combination
- • TxProfile SHALL only be used with evseId > 0
- • ChargingStationMaxProfile SHALL NOT use chargingProfileKind = Relative
- • First chargingSchedulePeriod.startPeriod SHALL always be 0
- • When an existing ChargingProfile.id is sent, it replaces the existing profile
| reasonCode | Cause |
|---|---|
TxNotFound | TxProfile sent but no active transaction on EVSE |
UnknownEVSE | evseId does not exist |
UnsupportedRateUnit | chargingRateUnit not in CS's ChargingScheduleChargingRateUnit config |
DuplicateProfile | stackLevel+purpose conflict on EVSE |
InvalidSchedule | Phase conflict or invalid schedule data |
K08 - Get Composite Schedule
Request the CS to report its effective combined charging schedule. The composite schedule is the minimum of all merged profile purposes.
GetCompositeScheduleRequest
{
"duration": integer, // REQUIRED - Length of requested schedule in seconds
"evseId": integer, // REQUIRED - 0 = grid connection total
"chargingRateUnit": "W" | "A" // Optional - Force a specific unit
}GetCompositeScheduleResponse
{
"status": "Accepted" | "Rejected",
"statusInfo": { ... }, // Optional
"schedule": { // Present only when status=Accepted
"evseId": integer,
"duration": integer,
"scheduleStart": "2024-01-01T00:00:00Z",
"chargingRateUnit": "W" | "A",
"chargingSchedulePeriod": [
{ "startPeriod": 0, "limit": 11000.0, "numberPhases": 3 },
{ "startPeriod": 3600, "limit": 6000.0, "numberPhases": 3 }
]
}
}K09 - Get Charging Profiles
Query installed charging profiles from a Charging Station. The CS responds with ReportChargingProfilesRequest messages containing the matching profiles.
GetChargingProfilesRequest
{
"requestId": integer, // REQUIRED - Correlates with ReportChargingProfilesRequest
"evseId": integer, // Optional - 0=CS-level profiles only, omit=all, >0=specific EVSE
"chargingProfile": { // REQUIRED - Filter criteria
"chargingProfilePurpose": "TxDefaultProfile", // Optional filter
"stackLevel": integer, // Optional filter
"chargingProfileId": [1, 2, 3], // Optional - list of specific IDs
"chargingLimitSource": ["CSO", "EMS"] // Optional - filter by source
}
}ReportChargingProfilesRequest
CS → CSMS (may send multiple if tbc=true)
{
"requestId": integer, // REQUIRED - Matches GetChargingProfilesRequest
"chargingLimitSource": "EMS" | "Other" | "SO" | "CSO", // REQUIRED
"evseId": integer, // REQUIRED - 0 = CS-level
"chargingProfile": [ChargingProfileType], // REQUIRED - Array of profiles
"tbc": boolean // Optional - default false. true = more reports coming
}K10 - Clear Charging Profile
Clear one or more charging profiles from the Charging Station. Either specify a specific profile ID or use filter criteria.
ClearChargingProfileRequest
{
"chargingProfileId": integer, // Optional - Specific profile ID to clear
"chargingProfileCriteria": { // Optional - Filter criteria
"evseId": integer, // Optional - 0=CS level, omit=all
"chargingProfilePurpose": "TxDefaultProfile", // Optional
"stackLevel": integer // Optional
}
}Important: ChargingStationExternalConstraints profiles cannot be cleared by
the CSMS via this message. If the only matching profiles are ExternalConstraints, the CS responds Unknown.
4. Smart Charging Types
K02-K04K02 - Central Smart Charging
CSMS controls charging power/current for specific EVs or entire CS. The CSMS sends charging profiles to dynamically adjust limits based on grid capacity, energy prices, or other external factors.
Sequence Flow
EV Driver EV Charging Station CSMS | | | | |-- plug in --------->| | | | |-- TransactionEventReq(Started)->| | | |<- TransactionEventResp ---------| | | | | | |<- set max current (from default profile) | | | | | | | | [CSMS decides to change limit] | | | |<-- SetChargingProfileReq -------| | | | (TxProfile, transactionId) | | | |--- SetChargingProfileResp ----->| | | | | | |<- adapt current per new profile |
CSMS Implementation
- • Use chargingProfilePurpose =
TxProfileand include the transactionId - • TxProfile overrules TxDefaultProfile for the current transaction only
- • After the transaction stops, the TxProfile is deleted
- • Recommended: Check the
offlineflag before sending a profile - • Omit the duration field so the profile lasts until the transaction ends
K03 - Local Smart Charging
Local Controller performs load-balancing among Charging Stations in a group. The CSMS role is limited to setting overall group limits and providing chargingPriority hints.
CSMS Responsibilities
- • Set the overall group limit on the Local Controller
- • Set TxDefaultProfile on connected Charging Stations
- • Receive TransactionEventRequests forwarded by Local Controller
- • Optionally provide
chargingPriorityin TransactionEventResponse
Local Controller Responsibilities
- • Receives overall group limit from external system or CSMS
- • Distributes capacity among Charging Stations
- • Uses chargingPriority to influence load distribution
- • Manages internal load balancing
Note: When chargingPriority is given in TransactionEventResponse, the Local Controller uses it for that transaction only. Default chargingPriority is 0 when unknown.
K04 - Internal Load Balancing
CS internally balances load across its EVSEs within a fixed grid connection limit. The CSMS only needs to set the initial limit; the CS handles balancing autonomously.
CSMS Role
- 1. Send a SetChargingProfileRequest with
ChargingStationMaxProfileatevseId=0to set the known physical grid connection limit. - 2. That's it! The CS handles internal balancing autonomously.
Requirements
- • ChargingStationMaxProfile can only be set at evseId=0
- • The combined energy flow of all EVSEs SHALL NOT exceed the ChargingStationMaxProfile limit
- • No CSMS involvement during balancing - the CS manages it internally
5. Transaction Profiles
K05-K07K05 - Remote Start Transaction with Charging Profile
Remotely start a transaction with a specific charging profile. The CSMS can include a charging profile in the RequestStartTransactionRequest.
Sequence Flow
External Trigger CSMS Charging Station
| | |
|-- remote start | |
| |-- RequestStartTransactionReq->|
| | (idToken, chargingProfile, |
| | remoteStartId=123) |
| |<- RequestStartTransactionResp-|
| | (status=Accepted) |
| | |
| | [CS applies profile]
| | |
| |<- TransactionEventReq(Started)|
| |-- TransactionEventResp ------>|CSMS Implementation
- • MAY include a chargingProfile in
RequestStartTransactionRequest - • The profile SHALL have chargingProfilePurpose =
TxProfile - • DO NOT include transactionId in the profile (transaction doesn't exist yet)
- • If CS doesn't support Smart Charging, it will ignore the profile but still start the transaction
- • If CS supports Smart Charging but receives invalid profile, it responds
Rejectedwith reasonCode "InvalidProfile" or "InvalidSchedule"
K06 - Offline Behavior Smart Charging During Transaction
CS continues using the TxProfile while offline. The CSMS role is to proactively send a TxProfile while the connection is still active.
CSMS Action
- 1. Send SetChargingProfileRequest with a
TxProfilefor the ongoing transaction - 2. If CS goes offline, it continues using this profile
- 3. Profile persists until transaction ends or CS reconnects
CS Behavior
- • If profile was set before going offline: continue using it
- • If no profile was set before going offline: charge without constraints
- • Falls back to TxDefaultProfile and ChargingStationMaxProfile if TxProfile expires
K07 - Offline Behavior Smart Charging at Start of Transaction
CS uses TxDefaultProfile for transactions started while offline. This ensures safe charging limits even without CSMS connectivity.
CSMS Implementation
- 1. Proactively send a SetChargingProfileRequest with
TxDefaultProfileto Charging Stations that may go offline. - 2. When the CS starts a transaction while offline, it will use the installed TxDefaultProfile.
- 3. This ensures safe charging limits even without CSMS connectivity.
Best Practice: Set a conservative TxDefaultProfile (e.g., low default like 6A) on Charging Stations that may experience connectivity issues. This protects the grid and ensures safe operation during offline periods.
6. External Limits
K11-K14External systems (DSO, EMS, smart meter) can set charging limits via non-OCPP protocols. The CS reports these limits to the CSMS using NotifyChargingLimit and ClearedChargingLimit messages.
K11 - Set/Update External Charging Limit With Ongoing Transaction
CS informs CSMS about external charging limit during an active transaction. Triggered by an external control system setting a grid limit.
Sequence Flow
External Control System Charging Station CSMS
| | |
|-- set grid limit ----->| |
| |-- recalculate schedule |
| |-- set charging limit |
| | |
| |-- NotifyChargingLimitReq->| (if limit changed > LimitChangeSignificance)
| |<- NotifyChargingLimitResp-|
| | |
| |-- TransactionEventReq -->| (if rate changed > LimitChangeSignificance)
| | (trigger=ChargingRateChanged)
| |<- TransactionEventResp --|NotifyChargingLimitRequest
CS → CSMS
{
"chargingLimit": { // REQUIRED
"chargingLimitSource": "EMS" | "Other" | "SO", // NOT "CSO"
"isGridCritical": boolean // Optional
},
"evseId": integer, // Optional - Which EVSE is affected
"chargingSchedule": [ChargingScheduleType] // Optional - The schedule set by external system
}CSMS Implementation
- • Log/store the external limit information for monitoring/optimization
- • Respond with empty
NotifyChargingLimitResponse - • chargingLimitSource will NOT be "CSO" (always from external system)
- • Also expect a TransactionEventRequest with triggerReason = ChargingRateChanged if rate changed significantly
- • May use this info to adjust its own charging profiles to stay within external limit
K12 - Set/Update External Charging Limit Without Ongoing Transaction
CS informs CSMS about external limits when no transaction is active. Simpler flow than K11 (no TransactionEventRequest).
Sequence Flow
External Control System Charging Station CSMS
| | |
|-- set grid limit ----->| |
| | |
| |-- NotifyChargingLimitReq->|
| |<- NotifyChargingLimitResp-|CSMS Implementation
- • Receive NotifyChargingLimitRequest with limit info
- • Respond with empty NotifyChargingLimitResponse
- • Store the external limit for future scheduling decisions
- • The total load of all EVSEs SHALL NOT exceed the given external limit
K13 - Reset/Release External Charging Limit
CS notifies CSMS that an external charging limit has been released. The CSMS can now send updated charging profiles with higher limits.
Sequence Flow
External Control System Charging Station CSMS
| | |
|-- release grid limit ->| |
| |-- recalculate schedule |
| |-- release charging limit|
| | |
| |-- ClearedChargingLimitReq->|
| |<- ClearedChargingLimitResp-|
| | |
| |-- TransactionEventReq -->| (if ongoing tx & rate changed)
| | (trigger=ChargingRateChanged)
| |<- TransactionEventResp --|ClearedChargingLimitRequest
CS → CSMS
{
"chargingLimitSource": "EMS" | "Other" | "SO" | "CSO", // REQUIRED
"evseId": integer // Optional
}CSMS Implementation
- • Acknowledge with empty
ClearedChargingLimitResponse - • Update internal state - the external limit is no longer in effect
- • If a transaction is ongoing, also expect TransactionEventRequest with triggerReason = ChargingRateChanged
- • May now send updated charging profiles with higher limits
K14 - External Charging Limit with Local Controller
External limits flow through a Local Controller which distributes them among Charging Stations. The CSMS is mostly a passive observer.
Sequence Flow
External System Local Controller Charging Stations CSMS
| | | |
|-- set grid limit->| | |
| |-- NotifyChargingLimitReq --------->|
| |<- NotifyChargingLimitResp ---------|
| | | |
| |-- [Recalculate] | |
| | | |
| |-- SetChargingProfileReq(EVSE1) --->|
| |<- SetChargingProfileResp ----------|
| |-- SetChargingProfileReq(EVSE2) --->|
| |<- SetChargingProfileResp ----------|
| | | |
|-- release limit ->| | |
| |-- ClearedChargingLimitReq -------->|
| |<- ClearedChargingLimitResp --------|CSMS Implementation
- • Receive NotifyChargingLimitRequest from Local Controller - store external limit info
- • Respond with NotifyChargingLimitResponse
- • Receive ClearedChargingLimitRequest when the external limit is released
- • Respond with ClearedChargingLimitResponse
- • CSMS is mostly a passive observer - the Local Controller does the actual profile distribution
7. ISO 15118 Integration
K15-K17ISO 15118 enables high-level communication between the EV and Charging Station. The CSMS can receive charging needs from the EV and provide optimized charging schedules, as well as initiate renegotiation during charging sessions.
K15 - Charging with Load Leveling Based on High Level Communication
ISO 15118 EV communicates charging needs to CSMS via the CS. CSMS creates an optimized schedule based on EV requirements and grid constraints.
Sequence Flow
EV Charging Station CSMS | | | |-- ISO 15118 ---->| | | (charging needs)| | | |-- NotifyEVChargingNeedsReq ->| | | (evseId, chargingNeeds) | | |<- NotifyEVChargingNeedsResp --| | | (status: Accepted/Rejected/ | | | Processing) | | | | | | [CSMS calculates schedule] | | | | | |<-- SetChargingProfileReq ------| | | (TxProfile with schedule) | | |--- SetChargingProfileResp ---->| | | | |<- ISO 15118 ----| | | (charging schedule) |
NotifyEVChargingNeedsRequest
CS → CSMS
{
"evseId": integer, // REQUIRED - Must be > 0
"maxScheduleTuples": integer, // Optional - Max periods the EV supports per schedule
"chargingNeeds": { // REQUIRED
"requestedEnergyTransfer": "DC" | "AC_single_phase" | "AC_two_phase" | "AC_three_phase",
"departureTime": "2024-01-01T18:00:00Z", // Optional
"acChargingParameters": { // Present for AC charging
"energyAmount": integer, // Wh requested (includes preconditioning)
"evMinCurrent": integer, // Min amps per phase
"evMaxCurrent": integer, // Max amps per phase (incl. cable)
"evMaxVoltage": integer // Max voltage
},
"dcChargingParameters": { // Present for DC charging
"evMaxCurrent": integer, // REQUIRED - Max amps (incl. cable)
"evMaxVoltage": integer, // REQUIRED - Max voltage
"energyAmount": integer, // Optional - Wh requested
"evMaxPower": integer, // Optional - Max watts
"stateOfCharge": integer, // Optional - 0-100%
"evEnergyCapacity": integer, // Optional - Battery capacity in Wh
"fullSoC": integer, // Optional - 0-100%
"bulkSoC": integer // Optional - 0-100%
}
}
}NotifyEVChargingNeedsResponse
CSMS → CS
{
"status": "Accepted" | "Rejected" | "Processing",
"statusInfo": { ... } // Optional
}| Status | Meaning |
|---|---|
Accepted | CSMS can meet the EV's charging needs with current profiles |
Rejected | CSMS cannot meet the charging needs at all |
Processing | CSMS is calculating and will send SetChargingProfileRequest later (most common) |
CSMS Implementation
- • Parse the EV's charging needs (energy amount, departure time, min/max current/voltage)
- • Calculate an optimized charging schedule considering grid constraints, energy prices, other active transactions
- • Respond with status: Accepted (if existing profiles satisfy), Processing (most common), or Rejected
- • Send SetChargingProfileRequest with TxProfile containing up to 3 ChargingSchedule elements
- • Respect maxScheduleTuples - don't send more periods per schedule than EV supports
K16 - Renegotiation Initiated by CSMS
CSMS updates the charging schedule during an ISO 15118 session. The CS negotiates with the EV and reports the schedule the EV accepted.
Sequence Flow
CSMS Charging Station EV | | | |-- SetChargingProfileReq --->| | | (TxProfile, updated) | | |<- SetChargingProfileResp ---| | | | | | |-- ISO 15118 --------->| | | PowerDeliveryReq | | | (renegotiation) | | |<- ChargeParameterDiscoveryReq--| | |-- ChargeParameterDiscoveryRes->| | | (new schedule) | | | | |<- NotifyEVChargingScheduleReq| | |-- NotifyEVChargingScheduleResp->| |
NotifyEVChargingScheduleRequest
CS → CSMS
{
"timeBase": "2024-01-01T12:00:00Z", // REQUIRED - Reference time for schedule periods
"evseId": integer, // REQUIRED - Must be > 0
"chargingSchedule": { // REQUIRED - ChargingScheduleType
"id": integer,
"chargingRateUnit": "W" | "A",
"chargingSchedulePeriod": [
{ "startPeriod": 0, "limit": 7000.0 },
{ "startPeriod": 3600, "limit": 11000.0 }
],
"duration": integer,
"startSchedule": "2024-01-01T12:00:00Z"
}
}CSMS Implementation
- • Send SetChargingProfileRequest with updated TxProfile to trigger renegotiation
- • CS will negotiate with the EV via ISO 15118
- • Receive NotifyEVChargingScheduleRequest with the schedule the EV actually accepted
- • Respond with Accepted (acknowledgment; does NOT imply approval of the schedule)
- • If EV's accepted schedule doesn't match what CSMS wanted, send another SetChargingProfileRequest
K17 - Renegotiation Initiated by EV
EV requests updated charging parameters during an active session via ISO 15118. CSMS recalculates schedule based on new needs.
Sequence Flow
EV Charging Station CSMS | | | |-- ISO 15118 ------->| | | (new charging needs)| | | |-- NotifyEVChargingNeedsReq ->| | | (updated chargingNeeds) | | |<- NotifyEVChargingNeedsResp --| | | (status: Processing) | | | | | | [CSMS calculates] | | | | | |<-- SetChargingProfileReq -----| | |--- SetChargingProfileResp --->| | | | |<- ISO 15118 --------| | | (new schedule) | | | | | | |-- NotifyEVChargingScheduleReq->| | |<- NotifyEVChargingScheduleResp-|
CSMS Implementation
- • Receive NotifyEVChargingNeedsRequest with updated EV parameters (changed departure time, SoC, energy amount, etc.)
- • Respond with Processing status
- • Recalculate the charging schedule based on the new needs
- • Send SetChargingProfileRequest with an updated TxProfile
- • Receive NotifyEVChargingScheduleRequest with the schedule the EV accepted
- • Respond with Accepted
8. Reference
Quick ReferenceMessage Summary
Messages the CSMS SENDS (CSMS → CS)
| Message | Used In | Purpose |
|---|---|---|
SetChargingProfileRequest | K01, K02, K05, K06, K07, K16 | Set/update a charging profile |
ClearChargingProfileRequest | K10, K14 | Clear charging profiles |
GetCompositeScheduleRequest | K08 | Query effective composite schedule |
GetChargingProfilesRequest | K09 | Query installed profiles |
NotifyChargingLimitResponse | K11, K12, K14 | Acknowledge external limit notification |
ClearedChargingLimitResponse | K13, K14 | Acknowledge cleared external limit |
NotifyEVChargingNeedsResponse | K15, K17 | Respond to EV charging needs |
NotifyEVChargingScheduleResponse | K16, K17 | Acknowledge EV schedule notification |
Messages the CSMS RECEIVES (CS → CSMS)
| Message | Used In | CSMS Action |
|---|---|---|
SetChargingProfileResponse | K01, K02, K05, K06, K07, K16 | Check Accepted/Rejected status |
ClearChargingProfileResponse | K10, K14 | Check Accepted/Unknown status |
GetCompositeScheduleResponse | K08 | Parse composite schedule |
ReportChargingProfilesRequest | K09 | Receive and store reported profiles |
NotifyChargingLimitRequest | K11, K12, K14 | Receive external limit info, respond empty |
ClearedChargingLimitRequest | K13, K14 | Receive cleared limit, respond empty |
NotifyEVChargingNeedsRequest | K15, K17 | Parse EV needs, calculate schedule, send TxProfile |
NotifyEVChargingScheduleRequest | K16, K17 | Receive EV's accepted schedule, respond Accepted |
TransactionEventRequest | K02, K11, K13 | Handle triggerReason=ChargingRateChanged |
Configuration Variables
Key OCPP configuration variables that affect Smart Charging behavior:
| Variable | Component | Description |
|---|---|---|
Enabled | SmartChargingCtrlr | Whether smart charging is supported |
ChargingScheduleChargingRateUnit | SmartChargingCtrlr | Supported rate units ("W", "A", or both) |
ACPhaseSwitchingSupported | EVSE | Whether phase switching is supported |
LimitChangeSignificance | SmartChargingCtrlr | Min % change to trigger notifications |
ExternalControlSignalsEnabled | SmartChargingCtrlr | Whether external control signals are accepted |
EnableNotifyChargingLimitWithSchedules | SmartChargingCtrlr | Include schedules in NotifyChargingLimit |
Phases3to1 | EVSE | Whether EVSE supports switching 3-phase to 1-phase |
ChargingProfileEntries.maxLimit | SmartChargingCtrlr | Max number of profile IDs in GetChargingProfilesRequest |
Database Schema
Recommended database tables for implementing Smart Charging in the CSMS:
-- Charging Profiles
charging_profiles
- id (PK)
- charge_point_id (FK -> charge_points)
- profile_id (integer, the OCPP chargingProfile.id)
- evse_id (integer)
- stack_level (integer)
- charging_profile_purpose (enum: ChargingStationMaxProfile, TxDefaultProfile, TxProfile, ChargingStationExternalConstraints)
- charging_profile_kind (enum: Absolute, Recurring, Relative)
- recurrency_kind (enum: Daily, Weekly, nullable)
- valid_from (timestamptz, nullable)
- valid_to (timestamptz, nullable)
- transaction_id (string, nullable, for TxProfile only)
- created_at, updated_at
-- Charging Schedules
charging_schedules
- id (PK)
- charging_profile_id (FK -> charging_profiles)
- schedule_id (integer, the OCPP chargingSchedule.id)
- start_schedule (timestamptz, nullable)
- duration (integer, nullable)
- charging_rate_unit (enum: W, A)
- min_charging_rate (float8, nullable)
-- Charging Schedule Periods
charging_schedule_periods
- id (PK)
- charging_schedule_id (FK -> charging_schedules)
- start_period (integer)
- limit_value (float8)
- number_phases (integer, nullable)
- phase_to_use (integer, nullable)
-- External Charging Limits
external_charging_limits
- id (PK)
- charge_point_id (FK -> charge_points)
- evse_id (integer, nullable)
- charging_limit_source (enum: EMS, Other, SO, CSO)
- is_grid_critical (boolean, nullable)
- active (boolean)
- created_at, updated_atNote: This is a recommended schema. Adapt it to your existing database structure and naming conventions. Consider adding indexes on frequently queried fields like charge_point_id, evse_id, and transaction_id.