MeterValues is how a charger reports what its meter sees: energy, power, current, voltage, state of charge and more. It feeds live session displays, smart charging decisions, and in some setups billing. It is also the OCPP message with the most variation between vendors, so a parser that handles one charger perfectly can misread the next. This is part 6; part 5 covered the transaction messages these values belong to.
Message structure
[
2,
"mv-9010",
"MeterValues",
{
"connectorId": 1,
"transactionId": 880213,
"meterValue": [
{
"timestamp": "2026-10-26T10:30:00Z",
"sampledValue": [
{
"value": "1291804",
"context": "Sample.Periodic",
"measurand": "Energy.Active.Import.Register",
"location": "Outlet",
"unit": "Wh"
},
{
"value": "10950",
"context": "Sample.Periodic",
"measurand": "Power.Active.Import",
"unit": "W"
},
{
"value": "15.9",
"context": "Sample.Periodic",
"measurand": "Current.Import",
"phase": "L1",
"unit": "A"
},
{
"value": "54",
"context": "Sample.Periodic",
"measurand": "SoC",
"location": "EV",
"unit": "Percent"
}
]
}
]
}
]The response is empty: [3, "mv-9010", {}]. The request contains connectorId, an optional transactionId, and an array of MeterValue objects. Each MeterValue has a timestamp and an array of SampledValue. One message can carry several timestamps, which chargers use when they batch samples.
SampledValue fields
| Field | Required | Default when omitted |
|---|---|---|
value | Yes (string) | n/a |
context | No | Sample.Periodic |
format | No | Raw |
measurand | No | Energy.Active.Import.Register |
phase | No | No phase (total) |
location | No | Outlet |
unit | No | Wh |
Those defaults matter. A sampled value with only value set is an energy register reading in Wh at the outlet. Several chargers send exactly that, and a parser that requires measurand will drop all their data. Apply the defaults explicitly when you parse.
Measurands
| Group | Measurands |
|---|---|
| Energy registers (cumulative) | Energy.Active.Import.Register, Energy.Active.Export.Register, Energy.Reactive.Import.Register, Energy.Reactive.Export.Register |
| Energy intervals | Energy.Active.Import.Interval, Energy.Active.Export.Interval, Energy.Reactive.Import.Interval, Energy.Reactive.Export.Interval |
| Power | Power.Active.Import, Power.Active.Export, Power.Reactive.Import, Power.Reactive.Export, Power.Offered, Power.Factor |
| Current | Current.Import, Current.Export, Current.Offered |
| Other | Voltage, Frequency, Temperature, SoC, RPM |
"Import" means energy flowing from the grid into the vehicle; "Export" is the reverse. A .Register measurand is a running total; an .Interval measurand is the energy within the interval since the previous reading. Power.Offered and Current.Offered are what the charger is offering the vehicle, which is useful for verifying that a smart charging limit was applied (see part 9). SoC is only available where the charger receives it from the vehicle, which in practice means DC chargers.
Contexts
| context | Meaning |
|---|---|
Sample.Periodic | Regular sample during a transaction, every MeterValueSampleInterval seconds |
Sample.Clock | Clock-aligned sample, every ClockAlignedDataInterval seconds from midnight |
Transaction.Begin | Value at the start of the transaction |
Transaction.End | Value at the end of the transaction |
Interruption.Begin | Value when a power or communication interruption began |
Interruption.End | Value when the interruption ended |
Trigger | Sent in response to TriggerMessage |
Other | Anything else |
Two independent sampling schemes
OCPP 1.6 has two separate sampling mechanisms, each with its own configuration keys. Mixing them up is the most common configuration mistake around meter values.
Sampled data (per transaction)
MeterValueSampleInterval: seconds betweenSample.Periodicsamples during a transaction. 0 disables them.MeterValuesSampledData: comma-separated list of measurands to include, for exampleEnergy.Active.Import.Register,Power.Active.Import,SoC.StopTxnSampledData: measurands to include intransactionDataofStopTransaction.
Clock-aligned data
ClockAlignedDataInterval: seconds between clock-aligned samples, aligned to midnight. 900 produces readings at :00, :15, :30, :45. 0 disables them.MeterValuesAlignedData: measurands to include inSample.Clockreadings.StopTxnAlignedData: clock-aligned measurands to include inStopTransactiontransactionData.
Clock-aligned data is sent whether or not a transaction is in progress, so it is the tool for site-level energy reporting (and for measuring idle consumption). Readings sent outside a transaction have no transactionId. There are also ...MaxLength keys such as MeterValuesSampledDataMaxLength that tell you how many measurands each list can hold.
[2, "csms-cfg-1", "ChangeConfiguration", {"key": "MeterValuesSampledData", "value": "Energy.Active.Import.Register,Power.Active.Import,Current.Offered,SoC"}]
[3, "csms-cfg-1", {"status": "Accepted"}]
[2, "csms-cfg-2", "ChangeConfiguration", {"key": "MeterValueSampleInterval", "value": "60"}]
[3, "csms-cfg-2", {"status": "Accepted"}]A charger that does not support a measurand you list should reject the ChangeConfiguration. Not all do; some accept the list and then omit the unsupported value. Verify by looking at what actually arrives.
Phases and location
Phase values are L1, L2, L3, N, L1-N, L2-N, L3-N, L1-L2, L2-L3 and L3-L1. A three-phase charger reporting Current.Import usually sends three sampled values with L1, L2, L3, and sometimes a fourth with no phase for the total. Voltage might be line-to-neutral (L1-N) or line-to-line (L1-L2), which differ by a factor of about 1.73, so do not ignore the phase field when you display or alert on voltage.
Location values are Body, Cable, EV, Inlet and Outlet. Inlet is the grid side of the charger and Outlet the vehicle side; the difference between them is the charger's own losses and consumption. SoC normally comes with location EV, and Temperature with Body.
Units
The unit enumeration includes Wh, kWh, varh, kvarh, W, kW, VA, kVA, var, kvar, A, V, K, Fahrenheit and Percent, plus a Celsius value for temperature. The default is Wh. Normalise to Wh and W internally. The bug you will eventually meet is a charger sending energy in kWh without a unit field, which then parses as Wh and turns a 30 kWh session into 0.03 kWh. Sanity-check registers against meterStart and flag readings that are off by a factor of 1000.
Signed meter values
format can be Raw (a plain number) or SignedData, where value contains a signed data block from an eichrecht or similar calibration-law meter. The format of that block is meter-specific and is not defined in OCPP 1.6 itself. If you operate in a market that requires signed meter values for billing, store the signed blobs exactly as received and pass them through to the driver or roaming partner for verification.
Practical guidance
- Use
meterStartandmeterStopfor billing energy, andMeterValuesfor live display, graphs and smart charging feedback. - Do not configure 10-second sampling on a large fleet unless you need it. A 60-second interval is a common default for live session display.
- Expect
MeterValueswithouttransactionIdduring a transaction from some firmware. Associate them by connector and time window. - Registers can go backwards after a meter replacement or board swap. Treat a negative delta as a data quality event, not negative energy.
- Queued
MeterValuesarrive in bursts after reconnect, sometimes several hours of data in a few seconds. Make ingestion idempotent on connector, timestamp and measurand.
Key takeaways
- Apply the SampledValue defaults: no measurand means
Energy.Active.Import.Register, no unit meansWh. - Sampled data (per transaction) and clock-aligned data (by wall clock) are configured separately.
- Read
phase,locationandunitbefore interpreting any number.
Previous: Part 5, StartTransaction and StopTransaction. Next: Part 7, remote commands. For how meter data becomes billable amounts, see EV charging pricing models.

