PyOCMF
Python library for parsing, validating, and verifying OCMF (Open Charge Metering Format) signatures from electric vehicle charging stations.
Try it in your browser
Launch the Browser Demo - No installation required! Paste a record, open an XML file or scan a QR code, and check it directly in your browser using Pyodide.
Features
- Parse OCMF strings into validated Python objects
- Verify cryptographic signatures for data integrity
- Support for ECDSA with multiple curves (secp192k1, secp256k1, secp192r1, secp256r1, secp384r1, secp521r1, brainpool variants)
- Type-safe models using Pydantic
- Accepts every record the Transparenzsoftware accepts, reports spec deviations as warnings, and offers an optional strict mode
- Eichrecht compliance checks aligned with the Transparenzsoftware
- Command-line interface for verification, compliance checks and inspection
Installation
This installs the complete package with CLI tools and cryptographic signature verification.
Alternative installation options
Quick Start
from pyocmf import OCMF
# Parse an OCMF string
ocmf_string = 'OCMF|{"FV":"1.0","GI":"KEBA_KCP30",...}|{"SD":"3045..."}'
ocmf = OCMF.from_string(ocmf_string)
# Access payload data
print(ocmf.payload.GI) # Gateway ID: "KEBA_KCP30"
print(ocmf.payload.GS) # Gateway serial number
print(ocmf.payload.RD) # List of meter readings
# Verify signature with a hex or base64 public key (requires pyocmf[crypto])
is_valid = ocmf.verify_signature(public_key)
# Strings with the key appended (OCMF|payload|signature|key), as in QR codes for the
# Transparenzsoftware, verify without one; parsing them emits a SpecWarning
is_valid = OCMF.from_string(ocmf_with_key).verify_signature()
Command Line Interface
# Verify the signature and check Eichrecht compliance
ocmf 'OCMF|{"FV":"1.0",...}|{"SD":"3045..."}' --public-key 3059301306072A8648CE3D...
# XML files carry their public keys; their transactions are checked as a whole
ocmf charging_session.xml
# Check a begin and an end record as one transaction
ocmf check begin.xml end.xml
# Show the parsed record
ocmf inspect 'OCMF|{...}|{...}'
See the CLI Reference for details.
More Examples
Working with XML files
OCMF data is often distributed in XML format from CPO backends.
from pyocmf import OcmfContainer
container = OcmfContainer.from_xml("charging_session.xml")
for entry in container:
print(f"Gateway: {entry.ocmf.payload.GI}")
if entry.public_key:
is_valid = entry.verify_signature()
print(f"Signature: {'Valid' if is_valid else 'Invalid'}")
# Records sharing a transactionId are checked as one transaction, as the
# Transparenzsoftware does; other records are checked on their own
for result in container.check_eichrecht(errors_only=True):
print(result.transaction_id, "compliant" if result.is_compliant else result.issues)
Eichrecht compliance checking
Validate German calibration law requirements for charging transactions.
from pyocmf import OCMF
ocmf_begin = OCMF.from_string(begin_string)
ocmf_end = OCMF.from_string(end_string)
issues = ocmf_begin.check_eichrecht(ocmf_end, errors_only=True)
if not issues:
print("Transaction is Eichrecht compliant")
# A single record holding both the begin and the end reading is checked the same way
issues = OCMF.from_string(record_string).check_eichrecht(errors_only=True)
The checks follow the Transparenzsoftware. They compare the begin and end readings on law-relevant registers (loss-compensated registers take precedence) and report errors for a meter status other than OK, an energy error flag, a missing or repeated begin or end reading, decreasing values or timestamps, mismatching OBIS codes, units, serial numbers, event counters (format versions before 0.5) or pagination contexts, and invalid identification levels. Time synchronization, time error flags, cable loss, identification data mismatches and pagination gaps are reported as warnings.
Public key metadata
Extract structured metadata from public keys per OCMF spec Table 23.
Supported Signature Algorithms
PyOCMF supports the ECDSA signature algorithms defined in the OCMF specification:
- secp192k1, secp256k1 - Koblitz curves
- secp192r1, secp256r1, secp384r1, secp521r1 - NIST curves
- brainpool256r1, brainpoolP256r1, brainpool384r1 - Brainpool curves
- SHA256 and SHA512 hash functions
The cryptography package does not support secp192k1, so pyocmf verifies it with the
pure-Python ecdsa package, which pyocmf[crypto] also installs.
Error Handling
from pyocmf import OCMF, SignatureVerificationError, OcmfFormatError
try:
ocmf = OCMF.from_string(ocmf_string)
is_valid = ocmf.verify_signature(public_key)
except OcmfFormatError as e:
print(f"Invalid OCMF format: {e}")
except SignatureVerificationError as e:
print(f"Signature verification error: {e}")
All library errors derive from PyOCMFError.
Spec Deviations
pyocmf accepts every record the Transparenzsoftware
accepts. Values outside the OCMF specification, such as unknown codes, exceeded lengths
or missing mandatory fields, are kept as-is and reported as a SpecWarning instead of
failing to parse:
import warnings
from pyocmf import OCMF, OcmfContainer, SpecWarning
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always", SpecWarning)
ocmf = OCMF.from_string(ocmf_string)
for warning in caught:
print(warning.message)
Pass strict=True to reject non-compliant records instead. The deviation is raised as
the usual OcmfFormatError, OcmfPayloadError or OcmfSignatureError:
ocmf = OCMF.from_string(ocmf_string, strict=True)
container = OcmfContainer.from_xml("transaction.xml", strict=True)
On the command line, use --strict.
About OCMF
OCMF (Open Charge Metering Format) is a standardized format for metering data from electric vehicle charging stations. It ensures transparency and tamper-proof documentation of charging sessions, complying with legal requirements such as:
- EU Measuring Instruments Directive (MID)
- German Eichrecht (calibration law)
For more information about OCMF, visit safe-ev.de.