PHP2Shell alert: critical PHP flaws CVE-2026-109618 / 109619 — check your servers and get patched fast
HashTech Systems
EV Charging
Part 6 of 12

OCPP 1.6 MeterValues: Measurands, Contexts and Sampling

Reading OCPP 1.6 MeterValues correctly: SampledValue fields, measurands, contexts, sampled vs clock-aligned data, units, phases and common parsing bugs.

HashTech Engineering · October 26, 2026 · 5 min read

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

json
[
  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

FieldRequiredDefault when omitted
valueYes (string)n/a
contextNoSample.Periodic
formatNoRaw
measurandNoEnergy.Active.Import.Register
phaseNoNo phase (total)
locationNoOutlet
unitNoWh

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

GroupMeasurands
Energy registers (cumulative)Energy.Active.Import.Register, Energy.Active.Export.Register, Energy.Reactive.Import.Register, Energy.Reactive.Export.Register
Energy intervalsEnergy.Active.Import.Interval, Energy.Active.Export.Interval, Energy.Reactive.Import.Interval, Energy.Reactive.Export.Interval
PowerPower.Active.Import, Power.Active.Export, Power.Reactive.Import, Power.Reactive.Export, Power.Offered, Power.Factor
CurrentCurrent.Import, Current.Export, Current.Offered
OtherVoltage, 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

contextMeaning
Sample.PeriodicRegular sample during a transaction, every MeterValueSampleInterval seconds
Sample.ClockClock-aligned sample, every ClockAlignedDataInterval seconds from midnight
Transaction.BeginValue at the start of the transaction
Transaction.EndValue at the end of the transaction
Interruption.BeginValue when a power or communication interruption began
Interruption.EndValue when the interruption ended
TriggerSent in response to TriggerMessage
OtherAnything 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 between Sample.Periodic samples during a transaction. 0 disables them.
  • MeterValuesSampledData: comma-separated list of measurands to include, for example Energy.Active.Import.Register,Power.Active.Import,SoC.
  • StopTxnSampledData: measurands to include in transactionData of StopTransaction.

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 in Sample.Clock readings.
  • StopTxnAlignedData: clock-aligned measurands to include in StopTransaction transactionData.

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.

json
[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 meterStart and meterStop for billing energy, and MeterValues for 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 MeterValues without transactionId during 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 MeterValues arrive 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 means Wh.
  • Sampled data (per transaction) and clock-aligned data (by wall clock) are configured separately.
  • Read phase, location and unit before 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.

Let's Talk

Ready to build something that lasts?

Whether it's a charging network, an AI rollout, or a core enterprise system — let's talk about what you're building.