Free OCPP Message Validator
Paste OCPP-J frames or a whole charger log to check every CALL, CALLRESULT and CALLERROR against OCPP 1.6 or 2.0.1.
What is an OCPP Message Validator?
OCPP, the Open Charge Point Protocol, is how EV chargers talk to the systems that run them. Over WebSockets, every message is a small JSON array: a CALL, a CALLRESULT or a CALLERROR. This validator checks those frames against OCPP 1.6 or 2.0.1, the two versions most chargers and central systems in service today speak over their WebSocket connection.
It reads single frames or whole logs with timestamps, matches each result to its call by message ID, and checks payloads of the core messages against schemas written from the OCPP JSON schema files. Missing fields, unknown properties, wrong types, values outside the allowed lists, overlong strings and bad timestamps are reported by path. Frames for actions without a schema here still have their structure, message ID and error codes checked, so a whole log can be pasted without filtering it first.
Key Features
Frames Checked
CALL, CALLRESULT and CALLERROR structure, message ID length and CALLERROR codes per version.
Core Messages
BootNotification, Heartbeat, Authorize, transactions, status, meter values and DataTransfer.
Results Matched
Each CALLRESULT is checked against the response schema of the CALL with the same ID.
Problems by Path
Every problem names the field, such as chargingStation.model, and what’s wrong.
Logs Stay Local
Charger logs, including ID tags, are checked in your browser and never uploaded.
Perfect for everyone
- Charger firmware engineers
- CSMS developers
- EV charging network operators
- Roaming platform teams
- Installers commissioning new sites and certification testers
How to Use the OCPP Message Validator
Pick the protocol version, then paste. The version matters because the same action name has a different payload in 1.6 and 2.0.1, so checking against the wrong one reports problems that aren’t there.
Choose the Version
OCPP 1.6 and 2.0.1 have different message shapes, so pick the one the charger speaks.
Paste Frames or a Log
One frame per line. Timestamps and arrows before the frame are ignored.
Read the Results
Each frame says whether its payload is valid, and lists any problems by path.
Check the Table
The table counts problems per frame, which helps in long logs.
OCPP Frames, Checked
Each row is OCPP-J traffic as a central system logs it, and each answer is this validator’s output for the version on the chip. The charger and its vendor are fictional. Some rows are valid and some carry the mistakes integrators run into most, so you can see how each problem is reported.
“2026-10-28T09:00:00Z <- [2,"19223201","BootNotification",{"chargePointVendor":"VoltWorks","chargePointModel":"VW-22","firmwareVersion":"3.4.1"}] 2026-10-28T09:00:00Z -> [3,"19223201",{"status":"Accepted","currentTime":"2026-10-28T09:00:00Z","interval":300}] 2026-10-28T09:12:40Z <- [2,"19223202","StartTransaction",{"connectorId":1,"idTag":"04A3B2C1","meterStart":15200,"timestamp":"2026-10-28T09:12:40Z"}] 2026-10-28T09:12:40Z -> [3,"19223202",{"idTagInfo":{"status":"Accepted"},"transactionId":4471}] 2026-10-28T10:05:11Z <- [2,"19223203","StatusNotification",{"connectorId":1,"errorCode":"GroundFailure","status":"Faulted","timestamp":"2026-10-28T10:05:11Z"}]”
“[2,"a1b2c3","BootNotification",{"chargingStation":{"model":"VW-22","vendorName":"VoltWorks"},"reason":"PowerUp"}]”
“[2,"a1b2c3","BootNotification",{"chargingStation":{"vendorName":"VoltWorks"},"reason":"Startup"}]”
“[2,"1","Heartbeat",{"now":true}]”
“[2,"1","StartTransaction",{"connectorId":"1","idTag":"012345678901234567890","meterStart":0,"timestamp":"yesterday"}]”
“[4,"19223204","NotImplemented","Requested Action is not known by receiver",{}]”
“[2,"tx-1","TransactionEvent",{"eventType":"Started","timestamp":"2026-10-28T09:12:40Z","triggerReason":"Authorized","seqNo":0,"transactionInfo":{"transactionId":"f2c1e8","chargingState":"Charging"},"idToken":{"idToken":"04A3B2C1","type":"ISO14443"},"evse":{"id":1,"connectorId":1}}]”
“[2,"7","GetDiagnostics",{"location":"ftp://logs.example.com/"}]”
“[3,"999",{"currentTime":"2026-10-28T09:00:00Z"}]”
“[2,"19223201","BootNotification",{"chargePointVendor":"VoltWorks"”
Messages You Will See Most
A charger’s day is a handful of messages repeated: it boots, sends heartbeats, authorises drivers, reports sessions and meter readings, and flags faults. These ten cover most logs.
BootNotification
The charger introduces itself after starting, with vendor and model.
“What must the response say for the charger to carry on?”
Heartbeat
A periodic ping that also returns the central system’s clock.
“Who sets the interval?”
Authorize
Asks whether an RFID card or other ID token may charge.
“What is the 1.6 field called?”
StartTransaction
OCPP 1.6: a session started, with connector, ID tag and meter start.
“What does the response assign?”
StopTransaction
OCPP 1.6: a session ended, with meter stop and a reason.
“Is a reason required?”
TransactionEvent
OCPP 2.0.1: one message for start, updates and end, with a sequence number.
“What are its event types?”
StatusNotification
A connector changed state, such as Available, Charging or Faulted.
“Which 1.6 field holds the fault?”
MeterValues
Readings such as energy, power and current, with timestamps.
“Is value a number in 1.6?”
DataTransfer
Vendor-specific data that the standard doesn’t cover.
“Which field is required?”
CALLERROR
The reply when a CALL can’t be processed, with a code and description.
“What does NotImplemented mean?”
How OCPP-J Frames Work
OCPP-J wraps every message in a JSON array sent over a WebSocket. The array’s shape tells the receiver what kind of message it is, which ID ties replies to requests, and where the payload sits. Every version of OCPP over JSON uses the same three shapes, so these rules hold for 1.6, 2.0.1 and 2.1 alike.
Message Type
The first item is 2 for a CALL, 3 for a CALLRESULT and 4 for a CALLERROR.
Message ID
A unique string up to 36 characters. The reply repeats it so the caller can match them.
Action
Only a CALL names its action. The reply’s schema follows from the call it answers.
Payload
A JSON object whose shape is fixed by the action and the OCPP version.
One Call at a Time
Each side may have only one CALL waiting for a reply, which keeps logs easy to follow.
Subprotocol
The WebSocket subprotocol, ocpp1.6 or ocpp2.0.1, decides which schemas apply.
OCPP 1.6 Versus 2.0.1
Both versions share the framing but differ in their messages. These are the changes that most often trip up a system being upgraded or one that speaks both versions. 2.0.1 isn’t backwards compatible, so a central system has to know which version each charger negotiated.
Transactions
1.6 uses StartTransaction and StopTransaction. 2.0.1 uses TransactionEvent for both and more.
Charging Station Model
2.0.1 nests vendor and model under chargingStation and requires a boot reason.
ID Tokens
1.6 has a plain idTag string. 2.0.1 has an idToken object with a type.
Connectors and EVSEs
2.0.1 addresses an EVSE and its connector, where 1.6 uses connectorId alone.
Status Values
2.0.1 replaces Preparing, Charging and Finishing with Occupied on the connector.
Meter Values
1.6 sends values as strings, 2.0.1 as numbers.
A Charging Session’s Status Changes
In OCPP 1.6 a connector reports its state with StatusNotification as a session goes on. Reading these in order is the quickest way to see where a session stalled, and the timestamps between them show how long each step took.
Available
The connector is free and ready. Sessions start and end here.
Preparing
A cable was plugged in or a card was presented, and the charger waits for the other.
Charging
Energy is flowing to the vehicle under an active transaction.
SuspendedEV and SuspendedEVSE
The car, or the charger, has paused charging, often because the battery is full or power is limited.
Finishing
The transaction stopped but the cable is still plugged in.
Faulted
Something is wrong. errorCode, info and vendorErrorCode say what.
Reading CALLERROR Codes
When a receiver can’t process a CALL, it answers with a CALLERROR. The code says which layer rejected the message, and the description and details usually say exactly why. Codes differ slightly between versions, which this validator checks for the version you pick.
NotImplemented
The receiver doesn’t know the action at all.
NotSupported
The action is known but this receiver doesn’t support it.
FormationViolation
The 1.6 code for a payload that doesn’t match the schema. 2.0.1 uses FormatViolation.
PropertyConstraintViolation
A field has a value outside what the schema allows, such as an unknown status.
TypeConstraintViolation
A field has the wrong type, such as a string where an integer belongs.
InternalError and GenericError
Something failed on the receiver’s side, so retrying later may work.
When to Validate OCPP
Whenever a charger and a central system disagree, the frames themselves are the evidence. Checking them against the schema settles which side broke the protocol.
Charger Integration
Find the field a new charger model sends wrongly before it reaches production.
Debugging Rejections
See why a central system answered with a FormationViolation or ignored a message.
Firmware Testing
Check every message after a firmware update against the protocol.
Migrating to 2.0.1
Compare frames from both versions while moving a fleet.
Learning OCPP
See what a valid message of each type looks like.
OCPP Pitfalls
Mistakes that break OCPP sessions, most of which a strict central system rejects with a CALLERROR while a lenient one silently ignores the bad field.
Numbers as Strings
connectorId must be an integer. "1" in quotes fails validation in strict systems.
Timestamps Without Zones
Use ISO 8601 with a zone, such as 2026-10-28T09:00:00Z.
Over-Long ID Tags
1.6 idTag allows 20 characters, which long UIDs can exceed.
Spelling in 1.6
The 1.6 error code is OccurenceConstraintViolation, misspelled in the standard itself.
Extra Properties
The schemas don’t allow undeclared fields. Vendor data belongs in DataTransfer.
Mixed Versions
Validating 1.6 frames as 2.0.1, or the reverse, reports problems that aren’t real.