Meter Values - CSMS Developer Guide
Based on OCPP 2.1 Edition 2 Specification (Part 2), Section J (Meter Values). This guide covers all meter value flows (J01–J03), including non-transaction meter values, transaction-related meter values, and ISO 15118 signed metering from the CSMS perspective using OCPP-J (JSON over WebSocket).
1. Overview
IntroductionThe Meter Values functional block enables Charging Stations to send periodic and/or clock-aligned meter readings to the CSMS. There are two categories of meter value delivery, each using a different transport message.
Key Concepts
Non-Transaction Meter Values
Clock-aligned readings sent via MeterValuesRequest when no active transaction exists on the EVSE, or for idle readings.
Transaction Meter Values
Sent via TransactionEventRequest with eventType = Updated during an active transaction.
ISO 15118 Signed Metering
Fiscally signed meter data from ISO 15118 charging loops, delivered as standard TransactionEventRequest messages with signed meter value data.
CSMS as Receiver
Both messages flow from Charging Station → CSMS. The CSMS is always the receiver and responder.
Message Categories
| Category | Transport Message | When Used |
|---|---|---|
| Non-transaction meter values | MeterValuesRequest | No active transaction on the EVSE, or clock-aligned idle readings |
| Transaction-related meter values | TransactionEventRequest | During an active transaction (eventType = Updated) |
Critical Rules
Important: Transaction-related MeterValues are never transmitted in MeterValuesRequest.
They are always sent via TransactionEventRequest.
Direction: Both messages flow from Charging Station → CSMS. The CSMS must always respond promptly. Failure to respond may cause the Charging Station to retry, potentially causing duplicate messages.
2. J01 — Receiving Non-Transaction Meter Values
CS-Initiated| Use Case ID | J01 |
| Direction | CS → CSMS (CS initiates) |
| Trigger | Clock-aligned interval when EVSE is not in a transaction |
| OCPP Messages | MeterValuesRequest / MeterValuesResponse |
Flow Diagram
Charging Station CSMS
| |
| MeterValuesRequest(evseId, meterValue)|
|-------------------------------------->|
| | <- Process & store meter data
| MeterValuesResponse() |
|<--------------------------------------|
| |Trigger Conditions
The Charging Station sends MeterValuesRequest when:
AlignedDataCtrlr.Interval> 0 AND the EVSE is not involved in a transaction- The CSMS has configured the station to periodically send clock-aligned meter values
AlignedDataSendDuringIdlecontrols whether these are only sent when no transactions are active
Incoming Request: MeterValuesRequest
OCPP Action: MeterValues · Direction: Charging Station → CSMS
{
"type": "object",
"required": ["evseId", "meterValue"],
"properties": {
"evseId": {
"type": "integer",
"minimum": 0,
"description": "EVSE identifier. 0 = main power meter of the Charging Station."
},
"meterValue": {
"type": "array",
"items": { "$ref": "#/definitions/MeterValueType" },
"minItems": 1,
"description": "One or more MeterValue elements, each with a timestamp and sampled values."
},
"customData": { "$ref": "#/definitions/CustomDataType" }
}
}| Field | Type | Required | Description |
|---|---|---|---|
evseId | integer (>= 0) | Yes | Identifies the EVSE. 0 means the main power meter (entire Charging Station). |
meterValue | MeterValueType[] | Yes | Array of meter value snapshots. Minimum 1 element. |
customData | CustomDataType | No | Vendor-specific extension data. |
Response: MeterValuesResponse
Requirement J01.FR.18: The CSMS MUST always respond with MeterValuesResponse.
Failing to respond may cause the Charging Station to retry the same message.
{
"type": "object",
"properties": {
"customData": { "$ref": "#/definitions/CustomDataType" }
}
}The response body is empty (no required fields). It is purely an acknowledgement.
{}{
"customData": {
"vendorId": "com.example.vendor"
}
}CSMS Processing Logic
When receiving a MeterValuesRequest,
implement the following:
- Validate the request against the JSON schema —
evseIdmust be >= 0,meterValuearray must have >= 1 element, each MeterValue must have a timestamp and >= 1 SampledValue - Identify the Charging Station and EVSE — look up the station by WebSocket connection/identity.
If
evseId == 0: data is from the main power meter (grid connection). IfevseId > 0: data is from a specific EVSE - Process each MeterValue — extract the timestamp (ISO 8601),
then for each SampledValue: read the value, determine the measurand
(default:
Energy.Active.Import.Register), context (default:Sample.Periodic), location (default:Outlet), and unit (default:Wh) - Apply the multiplier —
actual_value = value × 10^multiplier(default multiplier: 0). If signedMeterValue is present, store the signed data for auditability - Store the processed meter data in database
- Respond with
MeterValuesResponse(empty body:{})
Key Requirements (CSMS Perspective)
| Req ID | Rule |
|---|---|
J01.FR.02 | The evseId identifies which EVSE the samples were taken from. |
J01.FR.03 | When evseId is 0, the data is associated with the entire Charging Station. |
J01.FR.04 | When evseId is 0 and measurand is energy-related, the sample comes from the main energy meter. |
J01.FR.05 | Each MeterValue element SHALL contain a timestamp. |
J01.FR.06 | Each MeterValue SHALL contain one or more SampledValue elements. |
J01.FR.14 | When AlignedDataCtrlr.Interval > 0 and the EVSE is not in a transaction, the CS sends MeterValuesRequest for measurands in AlignedDataCtrlr.Measurands for all evseIds, locations, and phases. |
J01.FR.15 | The CS MAY use multiple MeterValuesRequest messages if data is too large for one message. |
J01.FR.17 | The timestamp of a MeterValue applies to all its SampledValues. |
J01.FR.18 | CSMS SHALL respond with MeterValuesResponse. Failure to respond may cause retries. |
Multiple Locations/Phases Handling
A Charging Station capable of measuring multiple locations/phases will send multiple MeterValuesRequest messages. For example, a station measuring Current.Import on Inlet (3 phases per
EVSE on each of 2 EVSEs) with AlignedDataCtrlr.Interval = 900 seconds sends:
MeterValuesRequestwithevseId=0, 3 SampledValue elements (one per phase, location = Inlet)MeterValuesRequestwithevseId=1, 3 SampledValue elements (one per phase, location = Outlet)MeterValuesRequestwithevseId=2, 3 SampledValue elements (one per phase, location = Outlet)
Note: When SampledDataRegisterValuesWithoutPhases is true, meter values
of measurand Energy.Active.Import.Register will only report the total energy over all phases without reporting individual phase values.
3. J02 — Receiving Transaction-Related Meter Values
CS-Initiated| Use Case ID | J02 |
| Direction | CS → CSMS (CS initiates) |
| Trigger | Periodic interval or clock-aligned interval during active transaction |
| OCPP Messages | TransactionEventRequest / TransactionEventResponse |
Flow Diagram
Charging Station CSMS
| |
| TransactionEventRequest(eventType=Updated, transactionId, |
| meterValue) |
|-------------------------------------------------------------->|
| | <- Process meter data
| | + link to transaction
| TransactionEventResponse() |
|<--------------------------------------------------------------|
| |Trigger Conditions
The Charging Station sends TransactionEventRequest with meter values when:
SampledDataTxUpdatedInterval> 0 and a transaction is active →triggerReason = MeterValuePeriodic- Clock-aligned data during a transaction →
triggerReason = MeterValueClock(context =Sample.Clock) - Transaction start →
eventType = Startedwith start meter values - Transaction end →
eventType = Endedwith end meter values
Incoming Request: TransactionEventRequest
OCPP Action: TransactionEvent · Direction: Charging Station → CSMS
{
"type": "object",
"required": ["eventType", "timestamp", "triggerReason", "seqNo", "transactionInfo"],
"properties": {
"eventType": {
"type": "string",
"enum": ["Started", "Updated", "Ended"]
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"triggerReason": {
"type": "string",
"enum": [
"AbnormalCondition", "Authorized", "CablePluggedIn",
"ChargingRateChanged", "ChargingStateChanged",
"CostLimitReached", "Deauthorized", "EnergyLimitReached",
"EVCommunicationLost", "EVConnectTimeout", "EVDeparted",
"EVDetected", "LimitSet", "MeterValueClock",
"MeterValuePeriodic", "OperationModeChanged", "RemoteStart",
"RemoteStop", "ResetCommand", "RunningCost",
"SignedDataReceived", "SoCLimitReached", "StopAuthorized",
"TariffChanged", "TariffNotAccepted", "TimeLimitReached",
"Trigger", "TxResumed", "UnlockCommand"
]
},
"seqNo": {
"type": "integer",
"minimum": 0,
"description": "Incremental sequence number for ordering transaction events."
},
"transactionInfo": {
"$ref": "#/definitions/TransactionType",
"description": "Contains transactionId and transaction state."
},
"meterValue": {
"type": "array",
"items": { "$ref": "#/definitions/MeterValueType" },
"minItems": 1,
"description": "Optional. Present when meter data is being reported."
},
"evse": { "$ref": "#/definitions/EVSEType" },
"idToken": { "$ref": "#/definitions/IdTokenType" },
"offline": { "type": "boolean", "default": false },
"numberOfPhasesUsed": { "type": "integer", "minimum": 0, "maximum": 3 },
"cableMaxCurrent": { "type": "integer" },
"reservationId": { "type": "integer", "minimum": 0 },
"costDetails": { "$ref": "#/definitions/CostDetailsType" },
"preconditioningStatus": {
"type": "string",
"enum": ["Unknown", "Ready", "NotReady", "Preconditioning"]
},
"evseSleep": { "type": "boolean" },
"customData": { "$ref": "#/definitions/CustomDataType" }
}
}{
"type": "object",
"required": ["transactionId"],
"properties": {
"transactionId": { "type": "string", "maxLength": 36 },
"chargingState": {
"type": "string",
"enum": ["EVConnected", "Charging", "SuspendedEV", "SuspendedEVSE", "Idle"]
},
"timeSpentCharging": { "type": "integer" },
"stoppedReason": {
"type": "string",
"enum": [
"DeAuthorized", "EmergencyStop", "EnergyLimitReached",
"EVDisconnected", "GroundFault", "ImmediateReset", "MasterPass",
"Local", "LocalOutOfCredit", "Other", "OvercurrentFault",
"PowerLoss", "PowerQuality", "Reboot", "Remote",
"SOCLimitReached", "StoppedByEV", "TimeLimitReached",
"Timeout", "ReqEnergyTransferRejected"
]
},
"remoteStartId": { "type": "integer" },
"operationMode": {
"type": "string",
"enum": [
"Idle", "ChargingOnly", "CentralSetpoint", "ExternalSetpoint",
"ExternalLimits", "CentralFrequency", "LocalFrequency",
"LocalLoadBalancing"
]
},
"tariffId": { "type": "string", "maxLength": 60 },
"transactionLimit": { "$ref": "#/definitions/TransactionLimitType" }
}
}Response: TransactionEventResponse
Requirement J02.FR.19: The CSMS SHALL respond with TransactionEventResponse.
Failure to respond may cause retries.
{
"type": "object",
"properties": {
"totalCost": {
"type": "number",
"description": "Running cost (when eventType=Updated) or final cost (when eventType=Ended)."
},
"chargingPriority": {
"type": "integer",
"description": "Temporary priority override. Range: -9 to 9. Default: 0."
},
"idTokenInfo": {
"$ref": "#/definitions/IdTokenInfoType",
"description": "Updated authorization status for the token."
},
"transactionLimit": {
"$ref": "#/definitions/TransactionLimitType",
"description": "Cost/energy/time/SoC limits for the transaction."
},
"updatedPersonalMessage": {
"$ref": "#/definitions/MessageContentType",
"description": "Message to display to the user on the Charging Station."
},
"customData": { "$ref": "#/definitions/CustomDataType" }
}
}Note: All fields are optional. A minimal acknowledgement
response is an empty JSON object: {}
CSMS Processing Logic
- Validate the request —
eventType,timestamp,triggerReason,seqNo, andtransactionInfoare required - Identify the transaction — look up by
transactionInfo.transactionId. If Started: create new record. If Updated: update existing. If Ended: finalize - Check seqNo for ordering — detect missing messages or out-of-order delivery. CS may drop intermediate messages when offline (J02.FR.12/13)
- Process meter values (if present) — for each MeterValue, extract
timestamp, then for each SampledValue parse value, measurand, context, location, phase,
unit, multiplier. Apply multiplier:
actual_value = value × 10^multiplier. Link meter data to the transaction - Handle triggerReason —
MeterValuePeriodic: periodic sampled data,MeterValueClock: clock-aligned data,SignedDataReceived: ISO 15118 signed meter data - Validate meter data integrity — register values (*.Register) MUST be monotonically increasing (J02.FR.16). Flag decreasing values as anomaly. Meter values SHALL be related to the EVSE of the transaction (J02.FR.22)
- Build the response — optionally include
totalCost(running or final),idTokenInfo,transactionLimit, orupdatedPersonalMessage
Meter Value Trigger Reasons
| triggerReason | Description | Expected meterValue |
|---|---|---|
MeterValuePeriodic | Periodic sampled data (every SampledDataTxUpdatedInterval seconds) | Yes — sampled measurands from SampledDataCtrlr.TxUpdatedMeasurands |
MeterValueClock | Clock-aligned data during transaction | Yes — measurands from AlignedDataCtrlr.Measurands with context Sample.Clock |
SignedDataReceived | ISO 15118 signed meter data received from EV | Yes — with signedMeterValue field populated |
Key Requirements (CSMS Perspective)
| Req ID | Rule |
|---|---|
J02.FR.02 | Each MeterValue element SHALL contain one or more SampledValue elements. |
J02.FR.10 | For eventType=Started/Updated with multiple meterValues: all timestamps must be within the current sampling interval. Only eventType=Ended can have values spanning multiple intervals. |
J02.FR.11 | When SampledDataTxUpdatedInterval > 0: CS sends TransactionEventRequest(eventType=Updated) with triggerReason=MeterValuePeriodic at every interval. |
J02.FR.12 | When offline and low on memory, CS MAY drop TransactionEventRequest(eventType=Updated) messages with triggerReason=MeterValueClock or MeterValuePeriodic. |
J02.FR.13 | When dropping messages, CS drops intermediate ones first (2nd, 4th, 6th, etc.), not from start or end. |
J02.FR.14 | CS MAY use multiple TransactionEventRequest messages with the same timestamp when data is too large for one message. |
J02.FR.16 | All "Register" values for a single transaction MUST be monotonically increasing. Exception: meter replacement. |
J02.FR.17 | Register values SHOULD be reported exactly as read from hardware and SHOULD NOT be re-based to zero. |
J02.FR.18 | Timestamp of a MeterValue applies to all its SampledValues. |
J02.FR.19 | CSMS SHALL respond with TransactionEventResponse. Failure may cause retries. |
J02.FR.20 | For eventType=Ended, CS MAY remove intermediate samples if data is too large. Removal should not affect billing. |
J02.FR.22 | Meter values in TransactionEventRequest SHALL be related to the EVSE of the transaction. |
Offline Behavior
When the Charging Station is offline:
- It MUST queue transaction-related meter values and send them when back online
- It MAY drop intermediate Updated events when low on memory (J02.FR.12)
- Dropped messages follow a pattern: intermediate ones (2nd, 4th, 6th) are removed first (J02.FR.13)
CSMS Detection: Use seqNo to detect gaps
and the offline flag to
identify queued messages that were sent while the station was disconnected.
4. J03 — ISO 15118 Charging Loop with Metering Information Exchange
CS-Initiated| Use Case ID | J03 |
| Direction | CS → CSMS (CS initiates) |
| Trigger | ISO 15118 charging loop with fiscal metering data exchange |
| OCPP Messages | TransactionEventRequest / TransactionEventResponse (same as J02) |
Flow Diagram
EV Charging Station CSMS
| | |
| [ISO 15118] | |
| ChargingStatusReq() | (AC Charging) |
|---------------------->| |
| | |
| ChargingStatusRes( | |
| MeterInfoRecord, | |
| ReceiptRequired: | |
| True) | |
|<-----------------------| |
| | |
| MeteringReceiptReq( | |
| Signature) | |
|---------------------->| |
| | |
| MeteringReceiptRes() | |
|<-----------------------| |
| | |
| | [OCPP] |
| | TransactionEventRequest( |
| | eventType=Updated, |
| | transactionID, timestamp, |
| | chargingState=Charging, |
| | Signed metervalues) |
| |---------------------------------------------->|
| | |
| | TransactionEventResponse() |
| |<----------------------------------------------|
| | |CSMS Role in J03
From the CSMS perspective, J03 is transparent — the CSMS handles this
exactly like J02. The ISO 15118 metering exchange happens between the EV and the Charging
Station. What reaches the CSMS is a standard TransactionEventRequest with:
eventType=UpdatedtriggerReason=SignedDataReceived(orMeterValuePeriodic)meterValuearray containingsignedMeterValuedata from the fiscal meter
Key Requirement
| Req ID | Rule |
|---|---|
J03.FR.04 | The Charging Station SHOULD NOT pass the raw ISO 15118 MeteringReceiptReq meter value in the TransactionEventRequest. Instead, it sends transaction-related meter values as per J02 flow. However, the implementation may ensure every fiscal meter value sent to CSMS was first acknowledged by the EV via MeteringReceiptReq. |
CSMS Processing
Handle identically to J02 TransactionEventRequest.
The presence of signedMeterValue in the SampledValue indicates
ISO 15118 signed metering data. The CSMS should:
- Store the
signedMeterData(Base64 encoded) for regulatory compliance - Note the
encodingMethod(e.g., "OCMF", "EDL") for later decoding - Optionally verify the signature using the
publicKeyif provided - Store the
signingMethodif present
5. Data Types & JSON Schemas Reference
ReferenceMeterValueType
A collection of sampled values taken at the same point in time.
{
"type": "object",
"required": ["timestamp", "sampledValue"],
"properties": {
"timestamp": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp. Applies to ALL sampledValues in this MeterValue."
},
"sampledValue": {
"type": "array",
"items": { "$ref": "#/definitions/SampledValueType" },
"minItems": 1,
"description": "One or more individual measurements."
}
}
}SampledValueType
A single measured value with metadata.
{
"type": "object",
"required": ["value"],
"properties": {
"value": { "type": "number", "description": "The measured value." },
"measurand": { "$ref": "#/definitions/MeasurandEnumType" },
"context": { "$ref": "#/definitions/ReadingContextEnumType" },
"phase": { "$ref": "#/definitions/PhaseEnumType" },
"location": { "$ref": "#/definitions/LocationEnumType" },
"signedMeterValue": { "$ref": "#/definitions/SignedMeterValueType" },
"unitOfMeasure": { "$ref": "#/definitions/UnitOfMeasureType" }
}
}Default Value Interpretation
A SampledValue with
only the value field
present defaults to:
- measurand:
Energy.Active.Import.Register - context:
Sample.Periodic - location:
Outlet - unit:
Wh(Watt-hour) - multiplier:
0(10^0 = 1)
This design saves mobile data bandwidth.
MeasurandEnumType
All possible measurement types:
Energy Measurands
| Measurand | Description | Unit |
|---|---|---|
Energy.Active.Import.Register | Default. Cumulative active energy imported. | Wh |
Energy.Active.Export.Register | Cumulative active energy exported (V2G). | Wh |
Energy.Active.Import.Interval | Energy imported during last interval. | Wh |
Energy.Active.Export.Interval | Energy exported during last interval. | Wh |
Energy.Active.Import.CableLoss | Cable loss energy. | Wh |
Energy.Active.Import.LocalGeneration.Register | Local generation register. | Wh |
Energy.Active.Net | Net active energy. | Wh |
Energy.Active.Setpoint.Interval | Setpoint energy during interval. | Wh |
Energy.Reactive.Import.Register | Cumulative reactive energy imported. | varh |
Energy.Reactive.Export.Register | Cumulative reactive energy exported. | varh |
Energy.Reactive.Import.Interval | Reactive energy imported during interval. | varh |
Energy.Reactive.Export.Interval | Reactive energy exported during interval. | varh |
Energy.Reactive.Net | Net reactive energy. | varh |
Energy.Apparent.Import | Apparent energy imported. | VAh |
Energy.Apparent.Export | Apparent energy exported. | VAh |
Energy.Apparent.Net | Net apparent energy. | VAh |
Power Measurands
| Measurand | Description | Unit |
|---|---|---|
Power.Active.Import | Instantaneous active power import. | W |
Power.Active.Export | Instantaneous active power export. | W |
Power.Active.Setpoint | Active power setpoint. | W |
Power.Active.Residual | Residual active power. | W |
Power.Reactive.Import | Instantaneous reactive power import. | var |
Power.Reactive.Export | Instantaneous reactive power export. | var |
Power.Offered | Maximum power offered to EV. | W |
Power.Import.Offered | Power import offered. | W |
Power.Import.Minimum | Minimum power import. | W |
Power.Export.Offered | Power export offered. | W |
Power.Export.Minimum | Minimum power export. | W |
Power.Factor | Power factor. | - |
Current & Voltage Measurands
| Measurand | Description | Unit |
|---|---|---|
Current.Import | Instantaneous current import. | A |
Current.Export | Instantaneous current export. | A |
Current.Offered | Maximum current offered to EV. | A |
Current.Import.Offered | Current import offered. | A |
Current.Import.Minimum | Minimum current import. | A |
Current.Export.Offered | Current export offered. | A |
Current.Export.Minimum | Minimum current export. | A |
Voltage | Instantaneous voltage. | V |
Voltage.Minimum | Minimum voltage. | V |
Voltage.Maximum | Maximum voltage. | V |
Other & Display Measurands
| Measurand | Description | Unit |
|---|---|---|
Frequency | Grid frequency. | Hz |
SoC | State of Charge of the EV battery. | % |
Display.PresentSOC | Present SoC for display. | % |
Display.MinimumSOC | Minimum SoC. | % |
Display.TargetSOC | Target SoC. | % |
Display.MaximumSOC | Maximum SoC. | % |
Display.RemainingTimeToMinimumSOC | Remaining time to min SoC. | s |
Display.RemainingTimeToTargetSOC | Remaining time to target SoC. | s |
Display.RemainingTimeToMaximumSOC | Remaining time to max SoC. | s |
Display.ChargingComplete | Charging complete flag. | - |
Display.BatteryEnergyCapacity | Battery energy capacity. | Wh |
Display.InletHot | Inlet hot indicator. | - |
EnergyRequest.Target | Target energy request. | Wh |
EnergyRequest.Minimum | Minimum energy request. | Wh |
EnergyRequest.Maximum | Maximum energy request. | Wh |
EnergyRequest.Minimum.V2X | V2X minimum energy request. | Wh |
EnergyRequest.Maximum.V2X | V2X maximum energy request. | Wh |
EnergyRequest.Bulk | Bulk energy request. | Wh |
ReadingContextEnumType
| Value | Description |
|---|---|
Interruption.Begin | Value at start of an interruption. |
Interruption.End | Value at end of an interruption. |
Other | Other context. |
Sample.Clock | Clock-aligned periodic reading. |
Sample.Periodic | Default. Periodic sampled reading (non-clock-aligned). |
Transaction.Begin | Value at start of transaction. |
Transaction.End | Value at end of transaction. |
Trigger | Value triggered by TriggerMessageRequest. |
LocationEnumType
| Value | Description |
|---|---|
Body | Body of the Charging Station. |
Cable | The charging cable. |
EV | The Electric Vehicle. |
Inlet | Inlet (grid connection side). |
Outlet | Default. Outlet (connector side). |
Upstream | Upstream of the Charging Station (grid side). WARNING: privacy-sensitive data. |
PhaseEnumType
| Value | Description |
|---|---|
L1 | Line 1 (measured on L1). |
L2 | Line 2 (measured on L2). |
L3 | Line 3 (measured on L3). |
N | Neutral. |
L1-N | Between Line 1 and Neutral. |
L2-N | Between Line 2 and Neutral. |
L3-N | Between Line 3 and Neutral. |
L1-L2 | Between Line 1 and Line 2. |
L2-L3 | Between Line 2 and Line 3. |
L3-L1 | Between Line 3 and Line 1. |
(absent) | Overall value (all phases combined). |
SignedMeterValueType
For digitally signed meter data (fiscal metering / ISO 15118).
{
"type": "object",
"required": ["signedMeterData", "encodingMethod"],
"properties": {
"signedMeterData": {
"type": "string",
"maxLength": 32768,
"description": "Base64 encoded. Contains signed data in the format specified by encodingMethod."
},
"signingMethod": {
"type": "string",
"maxLength": 50,
"description": "Method used to create the digital signature."
},
"encodingMethod": {
"type": "string",
"maxLength": 50,
"description": "Format used to encode meter data. E.g., 'OCMF' or 'EDL'."
},
"publicKey": {
"type": "string",
"maxLength": 2500,
"description": "Base64 encoded. Public key for signature verification."
}
}
}Public Key Format (J02.FR.23)
The publicKey field,
when present, is RECOMMENDED to follow the format:
<marker>:<encoding>:<content-type>:<printed-public-key><marker>="oca"<encoding>="base16","base32", or"base64"<content-type>="asn1"<printed-public-key>= the public key as printed on the certified meter
UnitOfMeasureType
{
"type": "object",
"properties": {
"unit": {
"type": "string",
"maxLength": 20,
"default": "Wh",
"description": "Unit of measurement. Default 'Wh' for energy measurands."
},
"multiplier": {
"type": "integer",
"default": 0,
"description": "Exponent to base 10. E.g., multiplier=3 means value * 10^3 = value * 1000."
}
}
}Computing the Actual Value
actual_value = value × 10^multiplier| value | multiplier | Result |
|---|---|---|
1234 | 0 | 1234 Wh |
1234 | 3 | 1,234,000 Wh (= 1234 kWh) |
5678 | -3 | 5.678 Wh |
6. Configuration Variables
ReferenceThese variables are set on the Charging Station via SetVariablesRequest.
The CSMS should be aware of them to understand what data to expect.
Transaction Meter Values Configuration
| Variable | Description | Effect |
|---|---|---|
SampledDataCtrlr.TxStartedMeasurands | Comma-separated list of measurands for TransactionEventRequest(eventType=Started) | Defines which measurands appear in transaction start messages |
SampledDataCtrlr.TxUpdatedMeasurands | Comma-separated list of measurands for TransactionEventRequest(eventType=Updated) every TxUpdatedInterval | Defines which measurands appear in periodic transaction updates |
SampledDataCtrlr.TxUpdatedInterval | Interval in seconds between sampled meter data during transaction | 0 = no sampled data. E.g., 300 = every 5 minutes |
SampledDataCtrlr.TxEndedMeasurands | Comma-separated list of measurands for TransactionEventRequest(eventType=Ended) | Defines which measurands appear at transaction end. Measured every TxEndedInterval from start |
SampledDataCtrlr.TxEndedInterval | Interval in seconds for end-of-transaction measurands | 0 = only final values |
Clock-Aligned Meter Values Configuration
| Variable | Description | Effect |
|---|---|---|
AlignedDataCtrlr.Measurands | Comma-separated list of measurands for clock-aligned MeterValuesRequest | Defines what's in non-transaction clock-aligned readings |
AlignedDataCtrlr.Interval | Interval in seconds for clock-aligned readings (from midnight) | 0 = disabled. 900 = every 15 min (0:00, 0:15, 0:30, ...) |
AlignedDataCtrlr.TxEndedMeasurands | Measurands for clock-aligned data in TransactionEventRequest(eventType=Ended) | Defines clock-aligned measurands at end of transaction |
AlignedDataCtrlr.TxEndedInterval | Interval in seconds for clock-aligned data within TransactionEventRequest(eventType=Ended) | Similar to AlignedDataCtrlr.Interval but for transaction-end messages |
AlignedDataSendDuringIdle | Boolean | true = only send clock-aligned MeterValuesRequest when no transactions are active |
Upstream Measurands Configuration
Warning: Upstream measurands may be privacy-sensitive data. May be subject to regulation and legal liability. An explicit agreement may be required.
| Variable | Description | Effect |
|---|---|---|
SampledDataUpstreamMeasurands | Comma-separated list of upstream measurands | Included in TransactionEventRequest(eventType=Started/Updated) |
SampledDataUpstreamInterval | Interval in seconds for upstream measurands | How often upstream data is sampled |
AlignedDataUpstreamMeasurands | Comma-separated list of upstream measurands (clock-aligned) | Included in clock-aligned readings |
AlignedDataUpstreamInterval | Interval in seconds for upstream aligned data | How often upstream aligned data is sampled |
Signed Meter Values Configuration
| Variable | Description | Effect |
|---|---|---|
AlignedDataSignReadings | Boolean | true = CS retrieves signed meter values for clock-aligned data |
SampledDataSignReadings | Boolean | true = CS retrieves signed meter values for sampled data |
Other Configuration
| Variable | Description | Effect |
|---|---|---|
SampledDataRegisterValuesWithoutPhases | Boolean | true = only report total energy over all phases for Energy.Active.Import.Register, not individual phases |
7. Validation Rules & Business Logic
ReferenceSchema Validation Checklist
For MeterValuesRequest:
-
evseIdis present and >= 0 -
meterValuearray is present with >= 1 element -
MeterValueeach has a valid ISO 8601 timestamp -
MeterValueeach has sampledValue array with >= 1 element -
SampledValueeach has a numeric value -
signedMeterValueif present: signedMeterData and encodingMethod are required
For TransactionEventRequest (meter-related):
-
eventType, timestamp, triggerReason, seqNo, transactionInfoare all present -
transactionInfo.transactionIdis present (max 36 chars) -
meterValueif present: same validation as MeterValuesRequest above
Business Logic Rules
| Rule | Description | Action |
|---|---|---|
| Register monotonicity | All .Register measurands for a single transaction MUST be monotonically increasing (J02.FR.16) | Flag decreasing register values. Exception allowed for meter replacement. |
| Register continuity | Register values SHOULD NOT be re-based to zero at transaction start (J02.FR.17) | Compare starting register of a new transaction to ending register of the previous transaction on the same connector. Differences may indicate missing energy. |
| Timestamp validation | MeterValue timestamps for eventType=Started/Updated must be within the current sampling interval (J02.FR.10) | (event_timestamp - SampledDataTxUpdatedInterval) < meterValue.timestamp <= event_timestamp |
| EVSE consistency | Meter values in TransactionEventRequest must relate to the EVSE of the transaction (J02.FR.22) | Cross-reference reported EVSE with transaction EVSE. |
| Sequence completeness | Use seqNo to verify all transaction events are received | Track expected seqNo per transaction. Gaps indicate dropped messages. |
| Offline handling | Messages with offline=true were queued | Process, but be aware timestamps may be in the past. |
Response Timing
- MUST respond promptly to both
MeterValuesRequestandTransactionEventRequest - Failure to respond causes the Charging Station to retry, potentially causing duplicate messages
- Keep processing logic lightweight or process asynchronously and respond immediately
8. Configuration Examples
ReferenceRecommended configurations the CSMS can push to Charging Stations via SetVariablesRequest.
Only Energy Register at Start/Stop of Transaction
SampledDataCtrlr.TxStartedMeasurands = "" (empty)
SampledDataCtrlr.TxUpdatedMeasurands = "" (empty)
SampledDataCtrlr.TxEndedMeasurands = "Energy.Active.Import.Register"
SampledDataCtrlr.TxEndedInterval = 0What the CSMS receives:
Energy register value only at transaction end in TransactionEventRequest(eventType=Ended).
Energy Register at Start, During, and End of Transaction
SampledDataCtrlr.TxStartedMeasurands = "Energy.Active.Import.Register"
SampledDataCtrlr.TxUpdatedMeasurands = "Energy.Active.Import.Register"
SampledDataCtrlr.TxUpdatedInterval = 300 (every 5 minutes)
SampledDataCtrlr.TxEndedMeasurands = "Energy.Active.Import.Register"
SampledDataCtrlr.TxEndedInterval = 0What the CSMS receives:
TransactionEventRequest(eventType=Started)with starting register valueTransactionEventRequest(eventType=Updated, triggerReason=MeterValuePeriodic)every 5 minutes with current register valueTransactionEventRequest(eventType=Ended)with final register value
Clock-Aligned Values During Transaction and Start/Stop at End
SampledDataCtrlr.TxStartedMeasurands = "" (empty)
SampledDataCtrlr.TxUpdatedMeasurands = "" (empty)
SampledDataCtrlr.TxEndedMeasurands = "Energy.Active.Import.Register"
SampledDataCtrlr.TxEndedInterval = 0
AlignedDataCtrlr.Measurands = "Energy.Active.Import.Register"
AlignedDataCtrlr.Interval = 300 (every 5 minutes)What the CSMS receives:
- Clock-aligned
MeterValuesRequestevery 5 minutes (when EVSE is idle) ORTransactionEventRequestwithtriggerReason=MeterValueClock(when in transaction) TransactionEventRequest(eventType=Ended)with final register value
9. Quick Reference: CSMS Response Templates
ReferenceMeterValuesResponse (J01)
{}TransactionEventResponse (J02/J03)
{}{
"totalCost": 12.50
}{
"totalCost": 12.50,
"transactionLimit": {
"maxCost": 50.00,
"maxEnergy": 60000,
"maxTime": 7200,
"maxSoC": 80
}
}{
"totalCost": 12.50,
"chargingPriority": 0,
"idTokenInfo": {
"status": "Accepted"
},
"transactionLimit": {
"maxCost": 50.00,
"maxEnergy": 60000
},
"updatedPersonalMessage": {
"format": "UTF8",
"content": "Charging at 22kW. Estimated completion: 14:30."
}
}