# OCPPLab — Full Content > Full-text corpus of OCPPLab marketing guides. OCPPLab is a browser-based OCPP and OCPI simulator for testing EV chargers, CPMS integrations, and roaming flows. Supports OCPP 1.6, OCPP 2.0.1, OCPP 2.1, OCPI 2.1.1, OCPI 2.2.1, and OCPI 2.3.0. Operator and protocol documentation is served by the docs app — ingest https://ocpplab.com/docs/llms-full.txt. See /llms.txt for the link-only index of marketing pages. # Documentation Operator guides and OCPP/OCPI protocol references live in the docs app at https://ocpplab.com/docs. Ingest the full docs corpus from https://ocpplab.com/docs/llms-full.txt. --- # Reference Guides ## OCPP AI Agents for EV Charging: A Complete Guide Source: https://ocpplab.com/blog/ai-agents-for-ev-charging How OCPP AI agents automate EV charging across 5 use cases — fault diagnosis to smart charging — plus architecture, guardrails, and how to test them safely. **Quick answer:** An OCPP AI agent watches a charging network's state, reasons under uncertainty, and acts through real protocols like OCPP and OCPI. Today they help with fault diagnosis, automated CPMS testing, smart charging, roaming reconciliation, and support. Building one needs guardrails and testing against virtual chargers before reaching production hardware. An OCPP AI agent for EV charging is software that watches the state of a charging network, decides what to do, and then acts on it through real protocols like [OCPP](/blog/what-is-ocpp), maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), and [OCPI](/blog/what-is-ocpi), governed by the [EVRoaming Foundation](https://evroaming.org/ocpi/). The difference from a normal script is that AI agents reason about messy, partial signals (a charger that boots but never starts a transaction, a roaming partner returning slow responses) and pick an action instead of following a fixed branch. This guide covers where AI agents for EV charging actually help today, how one is built, the safety problem nobody mentions until something resets a live charger, and how to test an agent before it reaches production hardware. Throughout, the examples use virtual chargers in an OCPP simulator so you can watch agent behavior without touching real sites. ## What Is an OCPP AI Agent in EV Charging? Three properties separate an agent from automation you already have: 1. **It observes real telemetry.** OCPP messages, StatusNotification streams, MeterValues, OCPI session and CDR data, monitoring probe results. 2. **It reasons under uncertainty.** It maps a fault signature to a likely cause even when the logs are incomplete or the charger behaves out of spec. 3. **It takes actions through tools.** It calls OCPP operations (RemoteStartTransaction, TriggerMessage, Reset), OCPI commands, or your own backend APIs, then checks whether the action worked. That loop — observe, reason, act, verify — is what makes it an agent rather than a dashboard. ## Where Do OCPP AI Agents Help EV Charging Today? ### 1. Fault diagnosis from OCPP telemetry A charger goes Faulted, or boots and never transacts. An agent reads the recent OCPP exchange, the StatusNotification error codes, and the connector history, then proposes the likely cause: a failed Authorize, a misconfigured heartbeat interval, a meter value that stopped reporting. Instead of an operator grepping logs, the agent returns a ranked hypothesis with the evidence it used. See the [OCPP error codes reference](/blog/ocpp-error-codes-reference) for the signatures these agents key off. ### 2. Automated CPMS and OCPP testing This is the most production-ready use case right now. An agent reads a release diff or a protocol spec, generates the OCPP test scenarios that matter, runs them against your [CPMS](/blog/what-is-csms), and reports what broke. It can expand coverage into edge cases a human writes last: reconnect storms, malformed payloads, out-of-order messages. OCPPLab runs this pattern as AI-assisted OCPP test automation against virtual chargers. ### 3. Smart charging and energy optimization An agent that holds site load limits, tariff windows, and live session demand can shape [smart charging](/blog/smart-charging-explained) profiles — the same domain the [ISO 15118](https://www.iso.org/standard/77845.html) vehicle-to-grid standard addresses on the vehicle side — in response to conditions instead of a static schedule. It sets charging profiles through OCPP, watches the resulting load, and adjusts. The reasoning step matters here because the inputs (grid signals, driver deadlines, price) conflict and the right tradeoff changes by the minute. ### 4. Roaming and CDR reconciliation Roaming disputes come from mismatched sessions and CDRs across partners. An agent can pull the OCPI Sessions and CDRs from both sides, line them up, and flag the specific field that disagrees (a timestamp, an energy total, a tariff lookup). That turns a manual reconciliation into a triaged queue. ### 5. Operator and driver support A support agent grounded in your charger fleet state can answer "why did my session stop" with the actual OCPP trace behind that session, not a generic FAQ. ## How Is an EV Charging Agent Built? Most working agents share the same shape: - **Perception layer.** Normalizes OCPP and OCPI traffic into structured events the model can reason over. Raw WebSocket frames are not enough; the agent needs session context, connector state, and history. - **Reasoning model.** An [LLM or SLM](/blog/llm-vs-slm-for-ev-charging) that takes the current state plus the goal and produces the next action. Model choice is a real decision, covered in the linked guide. - **Tools.** Typed wrappers over OCPP operations, OCPI commands, and your internal APIs. The agent calls these; it does not write raw protocol by hand, because a hallucinated OCPP payload sent to a real charger is a problem. - **Memory.** Recent actions and their outcomes, so the agent does not retry the same failed fix in a loop. - **Verification.** After each action, the agent checks the resulting telemetry to confirm the action did what it intended. ## The safety problem An agent that can send RemoteStartTransaction or Reset can also send them to the wrong charger, at the wrong time, in a loop. OCPP actions move physical hardware and energy. A model that is usually right is still occasionally wrong, and the charger it gets wrong is at a real site with a real driver. This is the reason most teams stall between a demo and production: the demo path is safe and the long tail is not. ## Guardrails that make agents shippable - **Scoped permissions.** The agent can read everything but can only write a small, explicit set of operations. RemoteStart yes, firmware update no. - **Human-in-the-loop for high-impact actions.** Diagnose autonomously, but require approval before any action that changes hardware state. - **Dry-run and rate limits.** Propose the action, show the predicted effect, cap how many real commands fire per minute. - **A sandbox.** Run the agent against virtual chargers first, where a wrong Reset costs nothing. ## How Do You Test an AI Agent Before Production? You cannot validate an agent on a spreadsheet of prompts. You have to run it against chargers that behave like real ones — including the failure modes you are asking it to handle — and watch what it does. That is what an [OCPP emulator](/blog/best-ocpp-emulators-compared) is for. Deploy virtual chargers that reproduce the exact fault you want the agent to diagnose, let the agent act, and check whether its OCPP commands were correct, safe, and effective. Because the chargers are virtual, a wrong action is a logged event, not a field incident. A practical test loop: 1. Define the scenario as a set of virtual chargers in known states (one Faulted, one stuck after BootNotification, one with stalled MeterValues). 2. Let the agent observe and act through OCPP. 3. Assert on the agent's actions, not just its text: did it send the right operation to the right charger? 4. Replay failures as regression cases so the agent does not lose a behavior on the next model update. OCPPLab is built for exactly this: spin up [virtual charger fleets](/use-cases/csms-testing), reproduce field bugs, and run agent behavior against them at scale before anything reaches a real site. ## LLM or SLM for the reasoning model? The model behind the agent drives its cost, latency, and where it can run. High-volume, narrow steps like fault classification often run better on a small model at the edge, while complex reasoning and test generation lean toward a large one. The right choice depends on the volume and complexity of the steps the agent runs. ## Where OCPPLab fits OCPPLab gives agents a safe place to act. Virtual chargers across [OCPP 1.6 and OCPP 2.0.1](/protocols/ocpp-1-6), full OCPI roaming partners, monitoring probes, and replayable failure scenarios — the environment you need to build, test, and trust an EV charging agent before it touches production hardware. [Start your testing](/dashboard) or see the [platform features](/features). --- ## LLM vs SLM for EV Charging: How to Choose the Right Model Source: https://ocpplab.com/blog/llm-vs-slm-for-ev-charging LLM vs SLM for EV charging software: when to use each across OCPP fault triage, edge monitoring, and AI agents, plus a hybrid pattern for 5,000+ chargers. **Quick answer:** For EV charging software, choose between large and small language models by workload, not by which is smarter. Use SLMs for high-volume, narrow, edge, or latency-sensitive jobs like OCPP fault classification and on-site monitoring; use LLMs for open-ended, low-volume reasoning like test generation and support chat. Most production systems use both. A large language model (LLM) is a general-purpose model with broad reasoning, usually run in the cloud. A small language model (SLM) is a compact model, often a few billion parameters or fewer, that can run on cheaper hardware or at the edge and is tuned for a narrower job. For EV charging software, picking between them is not about which is smarter. It is about where the work runs, how often it runs, and what data it touches. This guide gives you a decision framework instead of a winner, because the right answer changes by workload. ## Quick answer | Workload | Better fit | Why | |---|---|---| | OCPP fault classification at scale | SLM | High volume, narrow task, latency and cost matter | | Real-time monitoring at the charger or site | SLM | Runs at the edge, works offline, predictable cost | | Structured extraction from OCPP or OCPI logs | SLM | Pattern is narrow, output is constrained | | Test scenario generation from a spec | LLM | Needs broad reasoning and context | | Complex [agent](/blog/ai-agents-for-ev-charging) reasoning over conflicting signals | LLM | Hard tradeoffs, low volume, accuracy over cost | | Operator and driver support chat | LLM | Open-ended language, varied questions | Most production systems end up using both. The pattern is at the end of this guide. ## Why does model size matter in EV charging? Four pressures push EV charging workloads toward smaller models more than a typical SaaS app does: 1. **Scale.** A network with thousands of chargers generates a constant stream of [OCPP](https://openchargealliance.org/protocols/open-charge-point-protocol/) events. If every StatusNotification triggers a cloud LLM call, the bill and the latency add up fast. A narrow classification at that volume is an SLM job. 2. **The edge.** Charging sites have local controllers. Running a small model on-site means [smart charging](/blog/smart-charging-explained) and monitoring decisions keep working when the network link to the cloud is slow or down. 3. **Latency.** Some decisions are close to real time. A round trip to a large cloud model adds delay an edge SLM avoids. 4. **Data privacy.** Charging and energy data can be sensitive and regionally regulated. Keeping inference on-prem or in-region with an SLM avoids sending raw session data to a third-party model endpoint. ## When should you use an LLM? Reach for a large model when the task is open-ended and the volume is low enough that cost per call is not the constraint: - Generating [OCPP](/blog/what-is-ocpp) test scenarios from a protocol spec or a release diff. - Diagnosing a novel fault where the reasoning has to span several systems. - Operator-facing support that answers varied, unscripted questions. - Any step where being wrong is expensive and you would rather pay for accuracy. LLMs are also the faster path during development. Prototype the behavior with a capable model first, then decide later whether a smaller model can do the narrow version in production. ## When should you use an SLM? Reach for a small model when the task is narrow, the volume is high, or the work has to run at the edge: - Classifying OCPP faults into known categories. - Extracting structured fields from OCPP frames or [OCPI](https://evroaming.org/ocpi/) CDRs. - On-site monitoring that flags anomalies in MeterValues or session patterns. - Routing: deciding which requests are simple enough to answer locally and which to escalate. SLMs give you predictable cost, lower latency, offline operation, and tighter data control. The tradeoff is range: a small model handles the job it was tuned for and little beyond it. ## How should you route requests between an SLM and an LLM? The most resilient designs do not choose one model. They use a small model as a router and a large model as the fallback — an approach that echoes [NVIDIA Research's 2025 position paper on small language models in agentic systems](https://research.nvidia.com/labs/lpr/slm-agents/), which argues for heterogeneous systems that mix small and large models. 1. An SLM at the edge handles the high-volume, narrow steps: classify the fault, extract the fields, decide severity. 2. When the SLM is uncertain, or the case is complex, it escalates to an LLM in the cloud. 3. The LLM handles the long tail, and its answers can become training data that makes the SLM better at the next round. For an EV charging network this means most OCPP events are handled locally and cheaply, and only the hard cases pay for a large model. It also means the system degrades gracefully: if the cloud link drops, the edge SLM keeps the lights on. ## Worked example: OCPP fault triage Say you want to triage every StatusNotification with an error across a 5,000-charger fleet. - An LLM-per-event design is accurate but slow and expensive at that volume. - An SLM tuned on your historical OCPP faults classifies the common cases in milliseconds, on-site, for a fraction of the cost. - The handful it is unsure about escalate to an LLM that reasons across the full session and roaming context. You get cloud-grade quality on the cases that need it and edge economics on the cases that do not. ## Where does the training and evaluation data come from? A small model is only as good as the examples you tune and test it on, and real fault data is scarce by definition. You cannot wait for 5,000 chargers to fail in interesting ways. This is where an [OCPP emulator](/blog/best-ocpp-emulators-compared) earns its place. Generate labeled OCPP and OCPI sessions, including the rare failure modes, by running virtual chargers through scripted scenarios. Use them to tune the SLM and to build a held-out evaluation set that reflects real protocol behavior rather than synthetic prompts. ## How do you evaluate a model for charging workloads? Benchmarks built for general chat do not tell you whether a model handles OCPP. Evaluate on the work: 1. Build a test set of real and emulated OCPP or OCPI scenarios with known correct outcomes. 2. Run each candidate model (LLM and SLM) against it. 3. Score on the metric that matters for the task: classification accuracy, extraction correctness, or, for [agents](/blog/ai-agents-for-ev-charging), whether the resulting action was right and safe. 4. Compare cost and latency at your real volume, not at demo volume. OCPPLab gives you the environment for steps 1 and 3: virtual charger fleets across [OCPP 1.6](/protocols/ocpp-1-6) and [OCPP 2.0.1](/protocols/ocpp-2-0-1), reproducible failure scenarios, and the ability to run model-driven behavior against them at scale. ## Bottom line Use an LLM for open-ended reasoning, test generation, and support. Use an SLM for high-volume, narrow, latency-sensitive, or privacy-sensitive work at the edge. For most EV charging networks the answer is both, with a small model routing and a large model catching the long tail. Whichever you pick, validate it against chargers that behave like the real thing before it runs your network. [Start your testing](/dashboard) or explore [CPMS testing use cases](/use-cases/csms-testing). --- ## Best OCPP Simulators & Emulators in 2026 Compared Source: https://ocpplab.com/blog/best-ocpp-emulators-compared Compare the 4 best OCPP simulators and emulators for CPMS testing: cloud platforms, open-source libraries, and field tools for OCPP 1.6 and 2.0.1 workflows. **Quick answer:** The best OCPP emulator depends on what you need to validate. Choose a cloud platform to simulate thousands of chargers against a CPMS for repeatable regression and load testing, an open-source library for code-level control inside automated tests, or a lightweight mobile or desktop tool for single-charge-point smoke tests and field diagnostics. The best OCPP emulator depends on what you actually need to validate. Some teams need a **cloud platform** that can simulate thousands of chargers against a CPMS. Others need an **open-source library** they can script inside automated tests. Others only need a **single-charge-point utility** for smoke tests and field diagnostics. If you need version-specific validation first, go to [OCPP 1.6 testing](/protocols/ocpp-1-6) or [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). If you are actively comparing tools for a live project, see [platform features](/features), [CPMS testing](/use-cases/csms-testing), or [pricing](/pricing). ## Quick Answer Choose a **cloud OCPP emulator** if you need: - many concurrent virtual charge points - repeatable CPMS regression testing - load testing - buyer-ready reporting and faster setup Choose an **open-source OCPP emulator or library** if you need: - full code-level control - custom message generation - deep integration into an existing engineering workflow - lower software cost and higher internal maintenance effort Choose a **lightweight mobile or desktop emulator** if you need: - one charger at a time - quick smoke tests - simple field validation ## Comparison Table | Emulator Type | Best For | OCPP 1.6 | OCPP 2.0.1 | Scale | Setup Effort | |---|---|---|---|---|---| | **Cloud platform** | CPMS QA, load testing, release validation | Yes | Yes | High | Low | | **Open-source library** | Custom engineering and protocol edge cases | Yes | Usually yes | Medium | High | | **Open-source CPMS/test stack** | Development labs and protocol exploration | Yes | Mixed | Medium | Medium to high | | **Field/mobile emulator** | Smoke tests and technician workflows | Yes | Often limited | Low | Low | ## What Makes a Good OCPP Emulator? The best OCPP emulator is not just the tool that can send a `BootNotification`. As defined by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), OCPP covers far more than the happy path, so a good emulator should help you validate the behaviors that actually break in production: - reconnect logic - heartbeat timing - authorization and transaction flows - meter value cadence - status transitions - remote commands - malformed payload and timeout handling - mixed protocol version support If you are testing a commercial CPMS, an emulator that only handles the happy path is not enough. ## When Should You Use a Cloud OCPP Emulator? Cloud platforms are the fastest path when the goal is CPMS validation at scale. They are generally strongest at: - **multi-charger simulation** - **repeatable QA** - **performance and load testing** - **shared visibility for engineering, QA, and product teams** They also tend to be the most practical option when you need both [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1) without building all the protocol machinery yourself. ### Best for - CPMS vendors - charge point management teams - QA and release engineering - pre-production performance testing ### Tradeoffs - subscription cost - less low-level code control than a custom library ## When Should You Use an Open-Source Library? Open-source libraries are the right choice when your team wants full control over the emulator behavior and is willing to own the engineering work that comes with it. They are useful when you need to: - script unusual message sequences - generate malformed or adversarial payloads - embed emulator logic directly in a test suite - prototype protocol behavior quickly in code ### Best for - protocol engineers - backend developers - teams with strong internal test-automation capability ### Tradeoffs - more code to maintain - no managed scale by default - weaker dashboards and reporting unless you build them yourself ## When Should You Use an Open-Source Test Stack? Some teams prefer a broader open-source environment that helps them understand protocol behavior end to end. These stacks can be useful for: - lab exploration - interoperability debugging - reference behavior during development They can be valuable, but they usually require more time to install, configure, and keep aligned with your production needs. ## When Should You Use a Lightweight Field Emulator? Lightweight emulators are good for: - checking whether a CPMS endpoint is reachable - verifying a small number of core message flows - basic commissioning and support workflows They are usually not the right choice for serious regression or scale testing, but they are useful to keep in the toolbox. ## How Do You Choose the Best OCPP Emulator? ### Choose a cloud emulator if: - your CPMS must handle many concurrent chargers - you need to run repeatable test suites before releases - you need load testing and regression testing in one place - you want non-developers to use the tool as well ### Choose an open-source emulator if: - your team prefers code over UI - you need custom test logic and message injection - you are comfortable owning infrastructure and maintenance - your test scope is specialized enough that generic tooling is not sufficient ### Choose a field emulator if: - your scope is single-device smoke testing - you want instant setup - you do not need automation or scale ## Best OCPP Emulator by Use Case | Use Case | Best Emulator Type | |---|---| | **CPMS release regression** | Cloud platform | | **OCPP load testing** | Cloud platform | | **Custom protocol edge-case generation** | Open-source library | | **Field smoke tests** | Lightweight emulator | | **Learning OCPP internals** | Open-source library or reference stack | ## How Do OCPP 1.6 and 2.0.1 Emulator Needs Differ? Not every emulator is equally strong across versions. ### For OCPP 1.6 You should expect good coverage of the core [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) messages for: - BootNotification - Heartbeat - StatusNotification - Authorize - StartTransaction - MeterValues - StopTransaction - remote commands such as reset and remote start ### For OCPP 2.0.1 You should expect support for the [OCPP 2.0.1 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) workflows: - TransactionEvent - smart charging flows - device model or variable handling - higher-security and certificate-aware behaviors - richer error-path testing If the emulator only claims “OCPP 2.0.1 support” without clear workflow depth, inspect it carefully before depending on it. ## What Should Buyers Check Before Choosing? Use this checklist: - Does it support both [OCPP 1.6](/protocols/ocpp-1-6) and [OCPP 2.0.1](/protocols/ocpp-2-0-1)? - Can it reproduce realistic charger state transitions? - Can it simulate large numbers of concurrent charge points? - Does it support failure injection and reconnect behavior? - Can QA, product, and engineering all use it? - Does it help with [CPMS testing](/use-cases/csms-testing) and [OCPP load testing](/use-cases/ocpp-load-testing)? - Can it fit into CI/CD and recurring release validation? ## Why Choose OCPPLab as Your OCPP Emulator? OCPPLab is designed for teams that want a **cloud-based OCPP emulator** for commercial CPMS testing rather than a code-only toolkit. It is strongest when the job is to: - simulate many chargers at once - validate release candidates quickly - test OCPP 1.6 and OCPP 2.0.1 in one platform - combine emulator coverage with roaming and backend QA workflows That makes it a better fit for operational testing than lightweight or single-device tools, especially when the site under test needs realistic concurrency rather than one perfect happy-path session. For a broader tooling comparison, see [best OCPP testing tools compared](/blog/best-ocpp-testing-tools-compared). ## Frequently Asked Questions ### What is the difference between an OCPP simulator and an OCPP emulator? In practice, teams often use the words interchangeably. A simulator usually focuses on generating protocol behavior, while an emulator aims to mimic more of the real charger state model and runtime behavior. ### What is the best OCPP emulator for CPMS teams? Usually a cloud-based emulator platform, because CPMS teams care about repeatability, concurrency, regression coverage, and release confidence more than single-device manual tests. ### Can I use an open-source emulator for load testing? Yes, but you will usually need to build orchestration, observability, and scaling around it. That is the main tradeoff. ### Do I need separate emulators for OCPP 1.6 and OCPP 2.0.1? Not necessarily. A good platform can support both, but you should still validate version-specific workflows independently. ## Further Reading - [OCPP 1.6 testing](/protocols/ocpp-1-6) - [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1) - [OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1) - [The complete OCPP testing guide](/blog/ocpp-testing-guide) - [Best OCPP testing tools compared](/blog/best-ocpp-testing-tools-compared) - [CPMS testing without hardware](/use-cases/csms-testing) - [OCPP load testing workflows](/use-cases/ocpp-load-testing) --- ## OCPI 2.1.1 vs 2.2.1: Differences, Features & Upgrade Guide Source: https://ocpplab.com/blog/ocpi-2-1-1-vs-2-2-1 Compare OCPI 2.1.1 and OCPI 2.2.1 across roaming modules, hub support, ChargingProfiles, HubClientInfo, tariffs, and upgrade decisions for EV charging teams. **Quick answer:** OCPI 2.2.1 is a superset of OCPI 2.1.1 with three structural changes that matter most. **(1) Roles:** 2.2.1 adds Hub, NSP, NAP, and SCSP on top of 2.1.1's CPO/EMSP/OTHER. **(2) Modules:** 2.2.1 adds **ChargingProfiles** (smart charging through the roaming chain) and **HubClientInfo** (hub-aware participant discovery). **(3) Identifiers:** 2.1.1 uses ISO 3166-1 alpha-3 country codes (`FRA`, `NLD`); 2.2.1 switches to alpha-2 (`FR`, `NL`) plus a separate `party_id`. OCPI 2.2.1 also adds a `4xxx` Hub-error status-code class and a third credentials token (Token C) for hub-mediated routing. **OCPI 2.1.1 and OCPI 2.2.1** are the two versions most EV charging teams evaluate when they build roaming integrations, both published by the [EVRoaming Foundation](https://evroaming.org/). The specifications and reference schemas are hosted on [GitHub at ocpi/ocpi](https://github.com/ocpi/ocpi). OCPI 2.1.1 remains a common baseline for partner interoperability, while OCPI 2.2.1 expands the protocol for hubs, smarter tariff handling, and charging-profile workflows. If you need version-specific validation, start with [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) and [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1). If you are preparing for roaming rollout or partner onboarding, continue with [OCPI roaming testing](/use-cases/ocpi-roaming-testing) or [book an OCPI demo](/contact). ## What Are the Key Differences Between OCPI 2.1.1 and 2.2.1? | Feature | OCPI 2.1.1 | OCPI 2.2.1 | |---|---|---| | **Core roaming modules** | Yes | Yes | | **Credentials + version discovery** | Yes | Yes | | **Locations, Sessions, CDRs, Tariffs, Tokens, Commands** | Yes | Yes | | **Roles** | CPO, EMSP, OTHER (no Hub role) | CPO, EMSP, HUB, NSP, NAP, SCSP, OTHER | | **Country codes** | ISO 3166-1 alpha-3 (e.g. `FRA`, `NLD`, `DEU`) | ISO 3166-1 alpha-2 (e.g. `FR`, `NL`, `DE`) plus separate `party_id` | | **Hub support** | No native Hub role; hubs operate as CPO/eMSP peers | Native HUB role with hub-aware routing headers (`OCPI-from-*` / `OCPI-to-*`) | | **HubClientInfo module** | No | Yes | | **ChargingProfiles module** | No | Yes | | **Credentials handshake** | Token A → Token B | Token A → Token B → Token C (hub-aware) | | **Status codes** | 1xxx success, 2xxx client, 3xxx server | Same plus 4xxx Hub errors | | **Tariff model** | Core pricing model | Richer tariff metadata and structure | | **Migration difficulty** | Lower implementation surface | Larger implementation surface | | **Best fit** | Direct roaming partners and baseline interoperability | Hubs, smart charging, and broader future-ready roaming | ## The Short Answer Choose **OCPI 2.1.1** when you need the fastest path to stable roaming interoperability with the core modules: credentials, locations, sessions, CDRs, tariffs, tokens, and commands. Choose **OCPI 2.2.1** when you need hub-oriented behavior, smarter charging workflows, or a broader protocol surface for future roaming requirements. In practice, many teams still need to **support both**: 2.1.1 for existing partner compatibility and 2.2.1 for newer integrations. By the numbers — as of 2025, per the [EVRoaming Foundation](https://evroaming.org/) and the published [OCPI specifications](https://github.com/ocpi/ocpi): - **OCPI 2.1.1 defines 6 modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands) plus Credentials and Versions. Roles: CPO, EMSP, OTHER. - **OCPI 2.2.1 defines 8 modules** — the same 6 plus **ChargingProfiles** and **HubClientInfo**. Roles add **Hub, NSP, NAP, SCSP**. - **Country codes**: 2.1.1 uses [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) **alpha-3** (`FRA`, `NLD`, `DEU`); 2.2.1 switches to **alpha-2 + a separate `party_id`**. - **Status codes**: 2.1.1 uses ranges 1xxx / 2xxx / 3xxx; 2.2.1 adds a **4xxx Hub-error class** (15 codes). - **Credentials handshake**: 2.1.1 uses **Token A → Token B** (2 tokens); 2.2.1 uses **Token A → Token B → Token C** (3 tokens) for hub-aware routing. ## What Stays the Same Between the Two Versions? The good news is that the two versions share the same core model: - REST APIs over HTTPS - credentials handshake and token exchange - version discovery through `/versions` - core roaming entities such as locations, EVSEs, sessions, CDRs, tariffs, and tokens - CPO and eMSP role separation That means an upgrade from 2.1.1 to 2.2.1 is usually not a full rewrite. It is more often an expansion of your existing roaming implementation. ## Where Does OCPI 2.2.1 Add Real Value? ### 1. Hub-Centric Integrations OCPI 2.2.1 is a better fit for hub-connected ecosystems because it adds structures that are more practical for multi-party roaming environments. The most visible example is `HubClientInfo`, which helps systems exchange participant information in hub-based topologies. If your roadmap includes hub onboarding, version 2.2.1 is usually the safer long-term choice. ### 2. ChargingProfiles OCPI 2.2.1 introduces `ChargingProfiles`, which matters when smart charging needs to pass through the roaming chain instead of staying entirely inside the local CPO backend. This becomes relevant when: - an eMSP wants to influence charging behavior - a roaming workflow needs schedule-aware energy management - the backend stack must coordinate with [OCPP 2.0.1 smart charging flows](/protocols/ocpp-2-0-1), the charger-side protocol maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) ### 3. Richer Tariff and Field Coverage OCPI 2.2.1 gives teams more expressive tariff and metadata structures. That matters when pricing presentation, settlement clarity, or country-specific compliance expectations become stricter. ## How Do the Modules Compare? ### Credentials and Version Discovery No major conceptual change here. Both versions rely on the same practical sequence: 1. `GET /versions` 2. `GET /versions/{version}` 3. `POST /credentials` 4. token exchange and endpoint discovery This is why many teams can run both versions side by side without changing the whole architecture. ### Locations, Sessions, and CDRs Both versions support the core data flows roaming teams need every day: - publish charger locations and EVSE data - exchange live or near-real-time session updates - submit CDRs for settlement and invoicing For many operators, this is enough to ship a production roaming connection on 2.1.1. ### Tokens and Commands Again, both versions cover the main operational paths: - driver token synchronization - remote start and stop behavior - reservation and unlock style command flows If your product only needs baseline roaming enablement, 2.1.1 can remain perfectly serviceable. ### ChargingProfiles This is one of the clearest reasons to move to 2.2.1. When your roaming program needs charging control beyond static authorization and billing, 2.2.1 gives you the protocol surface to model it. ### HubClientInfo This is the other major differentiator. Hub-oriented roaming is easier to reason about in 2.2.1 because the protocol acknowledges those integration patterns more explicitly. ## When Should You Choose OCPI 2.1.1? Choose **OCPI 2.1.1** if: - you need fast partner onboarding with the core roaming modules - your partners already standardize on 2.1.1 - you do not need ChargingProfiles right now - your current architecture is direct CPO-to-eMSP interoperability rather than hub-heavy orchestration - you want a narrower implementation scope for the first production release For many teams, 2.1.1 is the right operational baseline and remains worth supporting for years. ## When Should You Choose OCPI 2.2.1? Choose **OCPI 2.2.1** if: - you need hub integration workflows - you need `HubClientInfo` - you need `ChargingProfiles` - your tariff and metadata requirements are growing - you want to reduce the risk of building against an older functional baseline while your product roadmap expands If you are building a newer roaming platform from scratch, 2.2.1 is often the better strategic default. ## Should You Support Both OCPI Versions? The safest commercial approach is often: - **support OCPI 2.1.1 for baseline compatibility** - **support OCPI 2.2.1 for advanced and future-facing integrations** This mirrors what many backend teams already do on the charger side with [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). ## How Do You Migrate from OCPI 2.1.1 to 2.2.1? ### Step 1: Keep Your Core Modules Stable Before adding 2.2.1-only features, make sure your 2.1.1 baseline is fully reliable: - credentials lifecycle - locations synchronization - sessions and CDR exchange - token authorization - command callbacks and error handling ### Step 2: Add Version-Aware Routing Make sure your implementation can distinguish version-specific endpoints and payload handling cleanly. This reduces regression risk and lets you run 2.1.1 and 2.2.1 side by side. ### Step 3: Add 2.2.1-Only Modules Deliberately Treat `ChargingProfiles` and `HubClientInfo` as explicit additions, not incidental changes. They usually need: - new payload validation - new persistence models - new async workflow handling - new interoperability tests ### Step 4: Test with Simulated Counterparties Do not wait for a live roaming partner or hub to discover payload mismatches. Simulate the opposite party and test the full flow before launch with [OCPI roaming testing](/use-cases/ocpi-roaming-testing). ### Step 5: Validate Mixed-Version Behavior If your platform will support both versions, test: - 2.1.1-only partner flows - 2.2.1-only partner flows - shared core modules across both versions - error handling when payload expectations diverge ## Example Decision Framework | Situation | Recommended Version | |---|---| | Launching a simple direct roaming integration | OCPI 2.1.1 | | Connecting to hub-oriented ecosystems | OCPI 2.2.1 | | Need smart charging over roaming | OCPI 2.2.1 | | Need maximum compatibility with existing partners | OCPI 2.1.1 plus 2.2.1 roadmap | | Building a future-facing roaming platform | Support both, prioritize 2.2.1 depth | ## Frequently Asked Questions ### Is OCPI 2.2.1 backward compatible with 2.1.1? Not automatically in the sense of using identical endpoints and payload expectations everywhere. The versions are closely related, but your implementation still needs explicit version-aware handling. ### Should I skip OCPI 2.1.1 and only implement 2.2.1? Only if you are certain your target partners and hubs do not require 2.1.1. Many teams still need 2.1.1 for practical interoperability. ### Is ChargingProfiles the main reason to adopt 2.2.1? It is one of the strongest reasons, especially for smart charging and advanced roaming workflows. Hub support is the other big reason. ### What is the safest production strategy? Support the 2.1.1 baseline cleanly, then expand to 2.2.1 where partner demand or product scope requires it. ## Further Reading - [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) - [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1) - [What is OCPI?](/blog/what-is-ocpi) - [OCPI endpoints complete reference](/blog/ocpi-endpoints-complete-reference) - [How to implement OCPI roaming](/blog/how-to-implement-ocpi-roaming) - [OCPI roaming testing](/use-cases/ocpi-roaming-testing) --- ## How to Test a CPMS: The Complete Testing Guide Source: https://ocpplab.com/blog/how-to-test-csms-complete-guide A complete guide to CPMS testing: 7 core methods—protocol conformance, load, security, integration, and roaming—plus a full checklist and CI/CD pipeline. **Quick answer:** CPMS testing is the systematic validation of your Charge Station Management System—the backend controlling, monitoring, and billing every EV charging session. It spans seven testing types: protocol conformance, integration, load, security, regression, end-to-end, and roaming. Combine virtual emulation for 95% of coverage with physical hardware for final acceptance to catch bugs before production. A single OCPP protocol bug can cause thousands of failed charging sessions, costing operators real money in lost revenue and avoidable truck rolls. Multiply that across a large network and the losses from a single regression add up quickly. CPMS testing is the systematic validation of your Charge Station Management System — the backend that controls, monitors, and bills every EV charging session on your network. It covers everything from OCPP message parsing to database consistency under load, from TLS certificate handling to roaming interoperability. This guide covers the **seven types of CPMS testing**, a detailed testing checklist, and how to build a testing pipeline that catches bugs before they reach production. ## What Is a CPMS? A CPMS (Charge Station Management System) is the central backend platform that communicates with charging stations over [OCPP](/blog/what-is-ocpp), manages user authorization, tracks energy delivery, and generates billing records (CDRs). It is the operational backbone of any EV charging network. If you are new to CPMS architecture, read our deep dive: [What Is a CPMS?](/blog/what-is-csms). For a hands-on walkthrough of building one, see [How to Build a CPMS](/blog/how-to-build-a-csms). The rest of this guide assumes you have a CPMS — either built in-house or procured from a vendor — and you need to test it thoroughly. ## What Are the 7 Types of CPMS Testing? Every mature CPMS testing program includes these seven categories. Skip any one of them and you leave a class of bugs undetected. ### 1. Protocol Conformance Testing Protocol conformance testing validates that your CPMS correctly implements every OCPP message flow according to the [OCPP specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) published by the Open Charge Alliance. This is the foundation — if your CPMS cannot parse a valid `BootNotification` request or sends a malformed `StatusNotification` response, nothing else matters. **What to validate:** - **Message schema compliance**: Every request and response conforms to the OCPP JSON schema (1.6) or the OCPP 2.0.1 JSON schema. Fields have correct types, required fields are present, and enums contain only valid values. - **Message flow sequencing**: The CPMS handles messages in the correct order. For example, a `StartTransaction` should only be accepted after a successful `BootNotification` and `StatusNotification` with status `Available`. - **Error handling**: The CPMS returns correct OCPP error codes (`NotImplemented`, `NotSupported`, `InternalError`, `ProtocolError`, `SecurityError`, `FormationViolation`, `PropertyConstraintViolation`, `OccurrenceConstraintViolation`, `TypeConstraintViolation`, `GenericError`) when it receives malformed or unexpected messages. See our [OCPP Error Codes Reference](/blog/ocpp-error-codes-reference) for the full list. - **Optional feature profiles**: If your CPMS advertises support for SmartCharging, FirmwareManagement, or Reservation profiles, every message in those profiles must be handled correctly. - **Version negotiation**: For OCPP 2.0.1, the CPMS must correctly negotiate the protocol version during the WebSocket handshake. **How to test it:** Send every valid OCPP message type to your CPMS and verify the response. Then send every invalid variation — missing required fields, wrong types, unknown enum values, oversized strings — and verify the error response. Automate this with a test harness that iterates through the OCPP schema. ### 2. Integration Testing Integration testing validates that your CPMS works with real-world chargers from different vendors. The OCPP specification leaves enough room for interpretation that two spec-compliant implementations can still fail to communicate. **Common vendor-specific behaviors:** - **ABB chargers** may send meter values with different measurand formats than what your CPMS expects. - **EVBox chargers** handle offline transaction queuing differently, sending batched `StartTransaction` and `StopTransaction` messages when reconnecting. - **Wallbox units** may use non-standard `DataTransfer` messages for proprietary features. - **Schneider Electric chargers** may have different timeout behaviors for `BootNotification` retry intervals. **What to test:** - Connect chargers from at least three different vendors and run full charging sessions. - Test the `DataTransfer` message handling for vendor-specific extensions. - Validate that your CPMS handles firmware version differences within the same vendor (charger firmware updates often change OCPP behavior subtly). - Test charger provisioning workflows — adding a new charger, updating its configuration, and decommissioning it. If you do not have access to physical chargers from multiple vendors, virtual charger emulators that replicate vendor-specific behaviors are essential. This is where tools like [OCPPLab](https://ocpplab.com) become critical — you can emulate different vendor behaviors without purchasing hardware. ### 3. Load Testing Load testing answers the question: **what happens when your entire network comes online at once?** After a power outage, a firmware update rollout, or a scheduled reboot window, thousands of chargers reconnect simultaneously. Each one sends a `BootNotification`, followed by `StatusNotification` messages for every connector, followed by queued offline transactions. Your CPMS must handle this surge without dropping connections or losing data. **Key metrics to measure:** - **Concurrent WebSocket connections**: Can your CPMS maintain 10,000+ persistent WebSocket connections simultaneously? 50,000? What is the ceiling before connections start failing? - **Message throughput**: How many OCPP messages per second can your CPMS process? A network of 10,000 chargers sending meter values every 30 seconds generates ~333 messages per second at steady state — but during a reconnection surge, you may see 10x that. - **Database write throughput**: Every `MeterValues` message, every `StartTransaction`, every `StopTransaction` triggers database writes. What is your write throughput under peak load? - **Response latency**: OCPP requires the CPMS to respond within a timeout window (typically 30 seconds, configurable). Under load, if your response latency exceeds this window, chargers will treat it as a timeout and may drop the connection. - **Memory consumption**: Long-running WebSocket connections accumulate state. Does your CPMS leak memory over hours of sustained load? **Load testing approach:** 1. Start with a baseline: 100 simulated chargers running normal charging sessions. 2. Ramp to 1,000, then 5,000, then 10,000 concurrent connections. 3. At each level, measure throughput, latency (p50, p95, p99), error rate, and resource consumption. 4. Simulate a "thundering herd" scenario: all chargers disconnect and reconnect within a 60-second window. 5. Run sustained load for 24+ hours to detect memory leaks and connection pool exhaustion. For a detailed comparison of physical and virtual load testing approaches, see the **Physical vs Virtual Testing** section below. ### 4. Security Testing A CPMS is a network-facing service that controls physical infrastructure and handles billing data. Security testing is not optional. **TLS and transport security:** - Validate that your CPMS enforces TLS 1.2 or higher on all WebSocket connections. - Test each OCPP 2.0.1 security profile: Security Profile 1 (HTTP Basic Auth over plain `ws://`, no TLS), Security Profile 2 (HTTP Basic Auth over `wss://` with server TLS certificate), and Security Profile 3 (mutual TLS — both server and client X.509 certificates over `wss://`). Note that OCPP 1.6 deployments using the Security Whitepaper edition 2 use different profile numbers (0–3) for an equivalent model. - Verify certificate validation: does the CPMS reject expired certificates, self-signed certificates (unless explicitly allowed), and certificates with wrong hostnames? - Test certificate rotation workflows without service interruption. **Authentication and authorization:** - Validate that unknown charge point identities are rejected at connection time. - Test RFID-based authorization with valid, expired, blocked, and unknown tokens. - Test remote start authorization — ensure the CPMS only accepts remote start requests from authenticated and authorized users. - Validate that [Plug & Charge (ISO 15118)](/blog/iso-15118-plug-and-charge) certificate chains, defined in [ISO 15118-2](https://www.iso.org/standard/55366.html), are verified correctly. **Input validation and injection:** - Send malformed JSON payloads to test for JSON injection vulnerabilities. - Test with oversized messages to validate buffer handling. - Send messages with unexpected Unicode characters, null bytes, and control characters. - Verify that charge point identifiers and user inputs are sanitized before database queries. **Penetration testing:** - Test WebSocket connection hijacking scenarios. - Attempt to impersonate a charge point by reusing a valid charge point identity from a different IP. - Test for information leakage in error messages. - Validate rate limiting on authentication attempts. Read our [OCPP WebSocket guide](/blog/ocpp-websocket-guide) for more on securing OCPP WebSocket connections. ### 5. Regression Testing Regression testing ensures that new code changes do not break existing charger compatibility. This is especially critical for CPMS platforms that support multiple OCPP versions (1.6 and 2.0.1) simultaneously. **What regression testing catches:** - A database migration that changes column types, breaking serialization of `MeterValues` timestamps. - A refactor of the authorization logic that accidentally rejects valid RFID tokens with leading zeros. - An optimization to WebSocket message handling that drops messages under specific timing conditions. - A new feature (e.g., smart charging) that introduces a side effect in the transaction lifecycle. **How to build a regression suite:** 1. **Record real traffic**: Capture OCPP message sequences from production chargers (sanitize sensitive data). Replay these sequences against your staging CPMS after every code change. 2. **Vendor-specific test suites**: Maintain a test suite for each charger vendor you support, covering their known OCPP behavior quirks. 3. **Golden file testing**: Store expected CPMS responses for a set of input messages. After each build, compare actual responses against the golden files. 4. **Backward compatibility checks**: If you support OCPP 1.6 and 2.0.1, run the full regression suite for both versions on every code change. ### 6. End-to-End Testing End-to-end testing validates the entire charging session lifecycle, from the moment a driver plugs in to the generation of a final billing record. **A complete e2e test covers:** 1. **Charger boot**: `BootNotification` → CPMS responds `Accepted` with a heartbeat interval. 2. **Status reporting**: Charger sends `StatusNotification` with `Available` for all connectors. 3. **Authorization**: Driver presents RFID → charger sends `Authorize` → CPMS responds `Accepted`. 4. **Transaction start**: Charger sends `StartTransaction` with connector ID, meter start value, and ID tag → CPMS responds with transaction ID. 5. **Meter values**: Charger sends periodic `MeterValues` with energy (Wh), power (W), current (A), voltage (V), SoC (%), and temperature readings. 6. **Smart charging** (optional): CPMS sends `SetChargingProfile` → charger acknowledges and adjusts power output. 7. **Transaction stop**: Driver unplugs → charger sends `StopTransaction` with meter stop value and reason → CPMS responds `Accepted`. 8. **CDR generation**: The CPMS generates a Charge Detail Record with accurate energy delivered, session duration, and cost calculation. 9. **Status update**: Charger sends `StatusNotification` with `Available` — ready for the next session. **Edge cases to cover in e2e tests:** - Driver unplugs mid-charge (abnormal stop). - Network drops during an active session — charger queues messages offline and replays on reconnect. - CPMS sends `RemoteStopTransaction` while a session is active. - Two sessions start simultaneously on a dual-connector charger. - Meter value discrepancies between start/stop values and intermediate readings. - Session that spans a clock rollover (midnight, DST change). ### 7. Roaming Testing If your charging network participates in roaming — allowing drivers from other networks to charge on your stations — you need to validate your [OCPI](/blog/what-is-ocpi) integration—the [open roaming standard](https://evroaming.org/ocpi/) maintained by the EVRoaming Foundation—with CPOs, eMSPs, and roaming hubs. **What to test:** - **Token synchronization**: eMSP tokens are correctly synced to your platform via OCPI `Tokens` module. Test with valid, expired, and revoked tokens. - **CDR delivery**: After a roaming session, the CDR is correctly formatted and delivered to the eMSP via OCPI `CDRs` module. - **Tariff exchange**: Your tariffs are correctly published via OCPI `Tariffs` module and correctly applied during roaming sessions. - **Real-time authorization**: `POST /commands/START_SESSION` from an eMSP triggers a `RemoteStartTransaction` on the correct charger. - **Location data**: Your charge point locations, EVSEs, and connectors are correctly published and updated via OCPI `Locations` module. - **Hub integration**: If you connect through a roaming hub like [Gireve](/blog/gireve-hub-integration) or Hubject, validate that messages correctly route through the hub. For a detailed comparison of roaming protocols, see [OCPI vs OICP vs OCHP](/blog/ocpi-vs-oicp-vs-ochp). ## CPMS Testing Checklist Use this checklist as a baseline for your testing coverage. Every item should have at least one automated test. ### BootNotification Handling - [ ] Accept valid `BootNotification` with all required fields - [ ] Handle vendor-specific optional fields (vendor name variations, firmware versions) - [ ] Return correct heartbeat interval in response - [ ] Handle duplicate `BootNotification` from the same charger (reconnect scenario) - [ ] Reject `BootNotification` from unknown/unauthorized charge points - [ ] Handle `BootNotification` with `Pending` status for chargers requiring configuration ### Transaction Lifecycle - [ ] `StartTransaction` with valid RFID token - [ ] `StartTransaction` with remote start (no local token) - [ ] `StopTransaction` with all standard stop reasons (`EmergencyStop`, `EVDisconnected`, `HardReset`, `Local`, `Other`, `PowerLoss`, `Reboot`, `Remote`, `SoftReset`, `UnlockCommand`, `DeAuthorized`) - [ ] Offline transactions: charger sends queued `StartTransaction` and `StopTransaction` after reconnection with correct timestamps - [ ] Transaction with zero energy delivered (plug in, immediate unplug) - [ ] Concurrent transactions on multi-connector chargers - [ ] Transaction ID uniqueness and sequential assignment ### Smart Charging Profile Management - [ ] `SetChargingProfile` with `TxDefaultProfile`, `TxProfile`, and the versioned max profile (`ChargePointMaxProfile` on 1.6; `ChargingStationMaxProfile` plus `ChargingStationExternalConstraints` on 2.0.1) - [ ] Charging schedule with multiple periods and power limits - [ ] Profile stacking and priority handling - [ ] `ClearChargingProfile` for specific profiles and bulk clearing - [ ] `GetCompositeSchedule` returns correct merged schedule - [ ] Profile validation: reject profiles with invalid timestamps, negative power values, or overlapping periods ### Firmware Update Workflows - [ ] `UpdateFirmware` with valid URI → charger downloads and installs - [ ] Firmware update status notifications (`Downloading`, `Downloaded`, `Installing`, `Installed`, `InstallationFailed`) - [ ] Firmware update during active charging session (should be deferred) - [ ] Invalid firmware URI handling - [ ] Firmware update retry on download failure ### Error Recovery - [ ] Network drop during active session — session state preserved, messages replayed on reconnect - [ ] CPMS restart — active sessions recovered from database, chargers reconnect gracefully - [ ] Timeout handling: charger does not respond to a `RemoteStartTransaction` within timeout window - [ ] Malformed OCPP message handling — return appropriate error, do not crash - [ ] WebSocket ping/pong keepalive and connection health detection - [ ] Database connection pool exhaustion — graceful degradation, not crash ### Authorization Flows - [ ] RFID authorization with local auth list - [ ] RFID authorization with online validation - [ ] Remote start via CPMS API → `RemoteStartTransaction` - [ ] Plug & Charge (ISO 15118) certificate-based authorization - [ ] Authorization cache behavior (cache hit, cache miss, cache expiry) - [ ] Blocked/expired/invalid token handling - [ ] Parent ID tag grouping (fleet cards) ### Concurrent Session Handling - [ ] 100 chargers running simultaneous sessions — all transactions recorded correctly - [ ] 1,000 chargers sending meter values simultaneously — no dropped messages - [ ] Mixed OCPP versions (1.6 and 2.0.1) running concurrently - [ ] WebSocket connection pool under concurrent load ### Database Consistency Under Load - [ ] Transaction records match exactly: start meter value + energy from meter values = stop meter value - [ ] No duplicate transaction IDs under concurrent writes - [ ] CDR amounts match calculated energy × tariff - [ ] Timestamps are stored and returned in correct timezone (UTC) - [ ] Database deadlocks under concurrent transaction updates ## Physical vs Virtual Testing | Dimension | Physical Testing | Virtual Testing | |---|---|---| | **Cost** | $2,000–50,000+ per charger model | $0–500/month for emulation platform | | **Setup time** | Days to weeks (procurement, installation, networking) | Minutes (configure and run) | | **Scale** | Limited by physical hardware (typically 1–10 chargers) | 10,000+ simulated chargers | | **Repeatability** | Low — physical conditions vary, manual steps | High — scripted, deterministic, CI/CD integrated | | **Edge case coverage** | Difficult — hard to simulate network drops, clock skew | Comprehensive — programmatic control over every variable | | **Vendor coverage** | One charger model per physical unit | Emulate any vendor behavior from a single tool | | **CI/CD integration** | Not practical | Native — run on every commit | | **Realism** | Highest — real hardware, real firmware | High — protocol-level accuracy, but no electrical/physical layer | **The practical approach**: Use virtual testing for 95% of your CPMS testing — protocol conformance, load testing, regression testing, and CI/CD integration. Reserve physical testing for final hardware acceptance testing and electrical safety validation. For a deeper analysis, read [Virtual vs Physical Testing for EV Chargers](/blog/virtual-vs-physical-testing). ## How Do You Build a CPMS Testing Pipeline? A production-grade CPMS testing pipeline integrates automated OCPP tests into your CI/CD workflow so that every code change is validated before it reaches production. ### Stage 1: Unit Tests (Run on Every Commit) Unit tests validate individual CPMS components in isolation: - OCPP message parser: correct serialization/deserialization for every message type. - Authorization logic: token validation, cache behavior, parent ID grouping. - Tariff calculation engine: energy cost, time cost, flat fees, tax calculations. - Database models: ORM mapping, constraint enforcement, migration compatibility. **Target: < 2 minutes execution time. Run on every commit.** ### Stage 2: Integration Tests (Run on Every PR) Integration tests validate CPMS behavior against simulated chargers: - Spin up a test CPMS instance with an in-memory or ephemeral database. - Connect 5–10 simulated chargers using an OCPP emulator. - Run the full charging session lifecycle for each OCPP version you support. - Validate database state after each test scenario. **Target: < 10 minutes execution time. Run on every pull request.** ### Stage 3: Load Tests (Run Nightly or Pre-Release) Load tests validate scalability: - Deploy the CPMS to a staging environment that mirrors production. - Ramp up to your target concurrent connection count (e.g., 10,000 chargers). - Run sustained load for 1–4 hours. - Capture and trend performance metrics: latency, throughput, error rate, memory. - Fail the build if any metric exceeds the defined threshold. **Target: 1–4 hours. Run nightly or before every release.** ### Stage 4: Regression Tests (Run Pre-Release) Regression tests replay recorded production traffic: - Use sanitized production OCPP message captures as test inputs. - Compare CPMS responses against golden file baselines. - Flag any response that differs from the expected baseline. - Include vendor-specific regression suites for every charger model you support in production. **Target: 30–60 minutes. Run before every release.** ### Stage 5: Security Scan (Run Weekly) - Dependency vulnerability scanning (CVEs in OCPP libraries, WebSocket frameworks, TLS libraries). - Static analysis for injection vulnerabilities. - TLS configuration validation (cipher suites, certificate chain, protocol version). - Authentication bypass testing. ## Which CPMS Bugs Does Virtual Testing Catch? These are real-world bugs that teams have caught through systematic virtual CPMS testing: **1. Off-by-one in meter value parsing**: A CPMS parsed the `sampledValue` array index incorrectly, reading voltage where it expected energy. This went undetected in production for weeks because most chargers sent meter values in a consistent order — until a new charger vendor sent them in a different order. Virtual testing with randomized meter value ordering caught it immediately. **2. Transaction ID overflow**: A CPMS used a 32-bit integer for transaction IDs. After 2.1 billion transactions, the ID wrapped to negative values. Chargers rejected negative transaction IDs, causing all new sessions to fail. A virtual load test simulating high transaction volumes would have caught this before production. **3. Timezone handling in CDRs**: A CPMS stored all timestamps in local time instead of UTC. When chargers in different timezones sent `StopTransaction` messages, the CDR duration calculations were wrong — sometimes negative. Virtual testing with chargers configured in multiple timezones exposed this immediately. **4. WebSocket connection leak**: A CPMS did not properly clean up WebSocket connections when chargers disconnected without sending a close frame (common during power outages). Over days, the connection pool filled up, and new chargers could not connect. A 24-hour virtual load test with periodic forced disconnections caught this. **5. Race condition in concurrent authorization**: Two `Authorize` requests arriving within milliseconds for the same RFID token caused a database deadlock. This only manifested at scale — virtual testing with 500 concurrent authorization requests reproduced it consistently. **6. Heartbeat interval ignored after reconnect**: After a charger reconnected, the CPMS sent a new heartbeat interval in the `BootNotification` response, but the charger-side cache was not cleared. The old interval persisted, leading to either excessive heartbeats (wasting bandwidth) or missed heartbeats (triggering false offline alarms). Virtual testing with configurable reconnection scenarios caught the discrepancy. **7. Smart charging profile rejected silently**: The CPMS sent a `SetChargingProfile` that the charger accepted, but the response contained an error detail in a vendor-specific field that the CPMS did not parse. The charger never applied the profile, but the CPMS assumed it did. Virtual testing with strict response validation caught the silent failure. ## What Tools Are Available for CPMS Testing? Several tools are available for CPMS testing, ranging from open-source libraries to commercial platforms: - **[OCPPLab](https://ocpplab.com)**: A cloud-based OCPP emulator that simulates chargers at scale. Supports OCPP 1.6 and 2.0.1, configurable vendor behaviors, and CI/CD integration via API. Designed specifically for CPMS testing. - **SteVe**: An open-source CPMS implementation that can serve as a reference for testing your own CPMS against a known baseline. - **OCPP.js**: A JavaScript library for building OCPP clients and servers. Useful for writing custom test harnesses. - **Custom test harnesses**: Many teams build their own using WebSocket libraries in Python, Go, or Node.js, combined with the OCPP JSON schemas for validation. For a detailed comparison of these tools, read [Best OCPP Testing Tools Compared](/blog/best-ocpp-testing-tools-compared). ## Frequently Asked Questions ### How many test cases does a thorough CPMS test suite need? A comprehensive CPMS test suite for OCPP 1.6 typically includes 200–400 test cases covering all message types, error conditions, and edge cases. OCPP 2.0.1 adds another 200–300 due to the expanded message set and security profiles. Load and performance tests add 20–50 more. The total depends on how many charger vendors and OCPP versions you support. ### Can I test a CPMS without physical chargers? Yes. Virtual OCPP emulators can simulate charger behavior at the protocol level, which is sufficient for 95% of CPMS testing — protocol conformance, integration, load, regression, and security testing. Physical chargers are only necessary for final hardware acceptance testing and validating electrical-layer behavior. See the **Physical vs Virtual Testing** comparison above. ### How do I test CPMS behavior during network outages? Use a virtual emulator that supports programmatic network control. Simulate a network drop during an active charging session: disconnect the WebSocket, wait a configured duration (30 seconds to 5 minutes), then reconnect and send the queued offline messages (`StartTransaction`, `MeterValues`, `StopTransaction` with historical timestamps). Validate that your CPMS correctly processes the replayed messages and reconstructs the session. ### What is the difference between OCPP conformance testing and CPMS testing? OCPP conformance testing is one component of CPMS testing. Conformance testing validates that your CPMS correctly implements the OCPP protocol specification. CPMS testing is broader — it also covers load testing, security testing, integration testing with multiple vendors, end-to-end session validation, roaming interoperability, and database consistency. ### How often should I run CPMS load tests? Run a lightweight load test (1,000 simulated chargers, 30 minutes) nightly as part of your CI/CD pipeline. Run a full-scale load test (10,000+ chargers, 4+ hours) before every production release and after any infrastructure changes (database migration, WebSocket server upgrade, scaling configuration changes). ### Should I test OCPP 1.6 and 2.0.1 separately? Yes. Maintain separate test suites for each OCPP version because the message schemas, security models, and feature sets differ significantly. However, also test them running concurrently — most production CPMS platforms support both versions simultaneously, and interactions between the two codepaths can introduce bugs. Read our comparison of [OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1) for the key differences. ### How do I validate CPMS billing accuracy? Create test scenarios with known energy delivery values and tariffs, then verify that the generated CDRs calculate the correct cost. Cover edge cases: sessions that span tariff changes (peak/off-peak transitions), sessions with minimum fees, sessions with multiple tariff components (energy fee + time fee + connection fee), and sessions with tax calculations. Compare your CDR output against a reference calculation for every test case. ### What should I do when a charger vendor reports a compatibility issue? First, capture the exact OCPP message exchange from the charger (most chargers have diagnostic logging). Replay that message sequence against your CPMS in a test environment to reproduce the issue. Once reproduced, add it as a permanent regression test case for that vendor. Fix the issue, verify the fix against the captured traffic, and ensure the fix does not break other vendor test suites. --- ## OCPP Implementation Guide: Build a CPMS for 1.6 & 2.0.1 Source: https://ocpplab.com/blog/ocpp-implementation-guide Step-by-step OCPP implementation guide to build a CPMS for OCPP 1.6 and 2.0.1, covering WebSocket setup, the 7 core messages, smart charging, and testing. **Quick answer:** Building an OCPP-compliant CPMS means creating a persistent, bidirectional WebSocket layer, not a REST API. Start with OCPP 1.6 and the core profile—BootNotification, Heartbeat, StatusNotification, Authorize, StartTransaction, StopTransaction, and MeterValues—then add transaction management, smart charging, security profiles, and resilience. Test thoroughly with virtual chargers before adding 2.0.1 support. Building an OCPP-compliant Charge Station Management System from the ground up is one of the more demanding backend engineering projects in the EV charging space. You are not just standing up a REST API. You are building a persistent, bidirectional communication layer that must handle unreliable network conditions, real-time state management across hundreds or thousands of physical devices, and a protocol specification that spans hundreds of pages. This guide walks you through the entire process, step by step, so you know exactly what to build and in what order. Before you write a single line of code, there are two decisions that shape everything downstream. First, which OCPP version will you target? [OCPP 1.6](/blog/ocpp-1-6-vs-2-0-1) is still the most widely deployed version and the one most charger manufacturers support today. OCPP 2.0.1 is the modern standard with significantly better security, device management, and smart charging capabilities, but hardware support is still catching up. If you are building a commercial product, you almost certainly need to support 1.6 today and 2.0.1 as your forward path. Second, which messages do you implement first? You do not need to support the entire specification on day one. Start with the core profile: BootNotification, Heartbeat, StatusNotification, Authorize, StartTransaction, StopTransaction, and MeterValues. That set alone gets a charger connected, authorized, and billing transactions. For hands-on validation strategy, pair this guide with [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). ## Prerequisites Before you begin implementation, make sure you have these components ready. A **WebSocket library** is the foundation. OCPP communicates over WebSockets, not HTTP. Choose a library in your language that supports both ws:// and wss:// (TLS-secured) connections, handles ping/pong frames natively, and gives you control over subprotocol negotiation. In Node.js, the ws library is the standard choice. In Python, websockets is the go-to. In Go, gorilla/websocket or nhooyr.io/websocket both work well. A **JSON schema validator** saves you enormous amounts of defensive coding. The [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) publishes JSON schemas for every OCPP message in both 1.6 and 2.0.1. Validate every incoming message against these schemas before processing it. This catches malformed payloads early and prevents subtle bugs from propagating through your system. A **persistent database** is essential for storing charger registrations, transaction records, meter values, and charging profiles. PostgreSQL is a strong default choice. You will need to handle high write throughput for meter values during active charging sessions, so plan your schema accordingly. **TLS certificates** are required for any production deployment. OCPP 2.0.1 mandates TLS for its higher security profiles, and even with 1.6, you should never run unencrypted WebSocket connections in production. Have your certificate chain, private key, and CA configuration ready. A solid understanding of the [OCPP protocol itself](/blog/what-is-ocpp) is obviously necessary. Read the [official OCPP specification document](https://openchargealliance.org/protocols/ocpp-protocols/) for your target version at least once end to end before starting implementation. ## Step 1: How Do You Set Up the WebSocket Server? Your [OCPP WebSocket server](/blog/ocpp-websocket-guide) is the entry point for every charger in your network. When a charge point boots up or reconnects, it initiates a WebSocket connection to a URL that typically follows the pattern `ws://your-CPMS.com/ocpp/{chargePointId}`. That trailing path segment is how you identify which charger is connecting. The first critical detail is **subprotocol negotiation**. When the charger opens the WebSocket handshake, it sends a `Sec-WebSocket-Protocol` header listing the OCPP versions it supports, for example `ocpp1.6, ocpp2.0.1`. Your server must inspect this header and respond with the single protocol version you want to use for that connection. If you support both versions, select the highest version you and the charger both support. If you do not recognize any of the offered protocols, reject the connection. Each charger connection must be treated as a **long-lived, stateful session**. Unlike HTTP request-response patterns, a single WebSocket connection stays open for hours, days, or even weeks. Your server needs to track each connection, associate it with the correct charger identity, and handle the lifecycle events: connection opened, message received, connection closed, and connection error. Plan your connection management carefully. You need a registry or map that associates charger identifiers with their active WebSocket connections. This registry is how your [CPMS](/blog/what-is-csms) sends commands down to chargers: you look up the charger's connection and write to it. If you are running multiple server instances behind a load balancer, you will need sticky sessions or a shared connection registry to route commands to the correct server instance. Implement **ping/pong** handling to detect dead connections. WebSocket ping frames are the heartbeat of the transport layer. If a charger stops responding to pings, the connection is dead and should be cleaned up. Most WebSocket libraries handle this automatically, but verify the behavior in yours. ## Step 2: How Do You Handle Core OCPP Messages? Every OCPP message over WebSocket follows a specific JSON array format. There are three message types. A **Call** message is a request, structured as `[MessageTypeId, UniqueId, Action, Payload]` where MessageTypeId is 2. A **CallResult** is a successful response, structured as `[3, UniqueId, Payload]`. A **CallError** is an error response, structured as `[4, UniqueId, ErrorCode, ErrorDescription, ErrorDetails]`. The UniqueId ties a response back to its originating request. Your implementation needs to track pending requests and match responses by their UniqueId. Build a pending request map with timeout handling. If you send a command to a charger and do not receive a response within 30 seconds (configurable), treat it as a timeout and handle accordingly. Your **message router** is the central dispatcher. When a Call message arrives, extract the Action field (for example, "BootNotification", "Heartbeat", "StatusNotification") and dispatch it to the appropriate handler function. This is a straightforward pattern: a map from action names to handler functions. Keep the router clean and ensure every registered action has a corresponding handler. Validate incoming messages at two levels. First, validate the JSON array structure itself: correct length, correct MessageTypeId, string UniqueId, string Action. Second, validate the Payload against the OCPP JSON schema for that specific action. Return a CallError with a `FormationViolation` or `PropertyConstraintViolation` [error code](/blog/ocpp-error-codes-reference) for malformed messages. ## Step 3: How Does the BootNotification Flow Work? BootNotification is the first meaningful OCPP message in every charger session. When a charger connects and sends BootNotification, it is announcing itself to your CPMS and providing its identity: vendor name, model, serial number, firmware version, and other metadata. Your handler needs to do several things. First, **identify the charger**. Look up the charger in your database by the charge point identifier from the WebSocket URL and optionally cross-reference with the serial number in the BootNotification payload. If this is a new charger you have never seen before, decide whether to auto-register it or reject it. In a production system, you typically require chargers to be pre-provisioned in your database before they can connect. Second, **set the response status**. Your BootNotification response includes a status field with three possible values: Accepted, Pending, or Rejected. Accepted means the charger is registered and operational. Pending means the charger should wait and try again, which is useful when you need an operator to manually approve new chargers. Rejected means the charger is not welcome. A rejected charger should disconnect, though it may retry later. Third, **set the heartbeat interval**. The response includes an `interval` field in seconds that tells the charger how often to send Heartbeat messages. A typical value is 300 seconds (5 minutes). This interval is how you control the balance between connection monitoring granularity and network traffic. Store the BootNotification data in your database along with a timestamp. This is your record of when chargers come online, what firmware they are running, and their hardware configuration. ## Step 4: How Do You Manage Transactions? Transaction handling is where your CPMS earns its keep. This is how charging sessions are started, tracked, and stopped, which directly feeds into billing. In **OCPP 1.6**, the flow uses discrete messages. A StartTransaction request arrives when a user initiates charging, containing the connector ID, ID tag (the user's RFID or other credential), meter start value, and timestamp. Your CPMS validates the ID tag (is this user authorized to charge?), creates a transaction record, assigns a transaction ID, and returns that ID in the response. During charging, MeterValues messages stream in with energy consumption data. When the session ends, a StopTransaction request provides the final meter reading, the reason for stopping, and optionally additional meter data. Your CPMS calculates the energy consumed, updates the transaction record, and triggers any billing processes. In **[OCPP 2.0.1](/blog/ocpp-1-6-vs-2-0-1)**, this entire flow is consolidated into a single TransactionEvent message with different event types: Started, Updated, and Ended. This is cleaner architecturally but requires you to handle all transaction lifecycle events through one handler with branching logic based on the event type. The 2.0.1 approach also provides richer data including cable plug-in/out events, EV communication setup, and more granular charging state transitions. Regardless of version, **authorization** is a critical sub-flow. When a charger requests authorization for an ID tag (via Authorize message or embedded in StartTransaction), your CPMS must quickly look up the tag in your database, check if it is valid and active, and respond. Speed matters here because the user is standing at the charger waiting. An Authorize response should come back in under a second. Handle **meter values** carefully. Chargers send periodic meter readings during a session, typically every 30 to 60 seconds. Each MeterValues message can contain multiple measurands: energy active import (kWh consumed), power active import (current power draw), current, voltage, state of charge, and temperature. Store all of these with timestamps. They are essential for billing accuracy, dispute resolution, and analytics. ## Step 5: How Do You Handle Status and Heartbeats? StatusNotification messages tell your backend what state each connector on a charger is in. The key statuses in **OCPP 1.6** are Available, Preparing, Charging, SuspendedEVSE, SuspendedEV, Finishing, Reserved, Unavailable, and Faulted. **OCPP 2.0.1** StatusNotification is only Available, Occupied, Reserved, Unavailable, or Faulted — charging progress is reported on `TransactionEvent`, not as a connector status of Charging. Your database should track the current status of every connector and maintain a status history log. Build a **status dashboard** early in your development process. Being able to see at a glance which chargers are online, which connectors are available versus charging versus faulted, is essential for operations. The StatusNotification data feeds directly into this. **Heartbeat** messages are simpler. They serve two purposes: confirming that the charger is still connected and operational, and synchronizing the charger's clock with your server's time. Your Heartbeat response must include a `currentTime` field with the current UTC timestamp. Chargers use this to correct clock drift, which matters for accurate timestamps on transaction and meter data. Monitor heartbeat patterns to detect charger issues. If a charger stops sending heartbeats at the expected interval (the one you set in the BootNotification response), it has likely gone offline. Implement an alert system that flags chargers as offline when they miss two or more consecutive heartbeat windows. ## Step 6: Smart Charging Smart charging is where OCPP goes from a simple communication protocol to a powerful grid management tool. The core mechanism is **SetChargingProfile**, a command your CPMS sends down to chargers to control how much power they can draw. A charging profile contains a **stack level** (priority, where higher numbers override lower), a **profile purpose**, and a **charging schedule** that defines power or current limits over time. OCPP 1.6 purposes are `ChargePointMaxProfile`, `TxDefaultProfile`, and `TxProfile`. OCPP 2.0.1 purposes are `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, `TxDefaultProfile`, and `TxProfile` — do not send `ChargePointMaxProfile` on a 2.0.1 session. The scheduling system is flexible. You can set a single flat limit ("never exceed 32A") or create time-based schedules ("22kW from midnight to 6am, 7kW from 6am to midnight") or even recurring schedules for weekly patterns. The charger evaluates all active profiles at each stack level and applies the most restrictive effective limit. Implement smart charging when you need **load management**. If you have multiple chargers sharing a limited power supply, your CPMS can dynamically distribute available capacity by updating charging profiles in real time based on total site consumption, grid signals, energy prices, or other inputs. This is one of the more complex areas of OCPP. Start with simple scenarios like setting a max power limit per charger and work up to dynamic load balancing across a site. ## Step 7: How Should You Handle Errors and Resilience? Real-world charger deployments are harsh on your assumptions about network reliability. Chargers operate on cellular connections that drop, WiFi that fluctuates, and networks that go down entirely. Your CPMS must be resilient to all of it. **Handle disconnects gracefully.** When a WebSocket connection drops, clean up the connection from your registry, mark the charger as potentially offline (do not immediately mark it offline; give it time to reconnect), and be ready to accept a new connection from the same charger. When the charger reconnects, it will send a new BootNotification and potentially replay transactions that happened while offline. **Offline transactions** are a critical edge case. If a charger loses connectivity during an active charging session, it continues charging and queues messages locally. When it reconnects, it sends those queued StartTransaction, MeterValues, and StopTransaction messages with timestamps from when they actually occurred, not when they were sent. Your CPMS must handle these out-of-order, delayed messages correctly, especially for billing accuracy. For a deeper understanding of how to handle OCPP errors systematically, refer to the [OCPP error codes reference](/blog/ocpp-error-codes-reference). **Message timeouts** need clear handling. When your CPMS sends a command to a charger and does not get a response, you need a retry strategy. But be careful: some commands are not idempotent. Sending RemoteStartTransaction twice could start two sessions. Design your retry logic per command type. **Implement connection rate limiting.** A misconfigured charger could attempt to reconnect hundreds of times per second. Your server must handle this without being overwhelmed. Apply backoff requirements and consider rejecting connections that exceed a threshold. ## Step 8: How Do OCPP Security Profiles Work? OCPP 2.0.1 introduced **mandatory** formal security profiles that address the glaring security gaps in core 1.6. The same model is available for 1.6 deployments through the optional **[Security Whitepaper](https://openchargealliance.org/ocpp-info-whitepapers/)** (edition 2 and later) (1.6 uses Profiles 0/1/2/3, while 2.0.1 uses Profiles 1/2/3 — see the comparison below). There are three security profiles in 2.0.1, each building on the previous. **Security Profile 1** uses basic HTTP authentication. The charger sends a username and password during the WebSocket handshake. Simple but better than nothing. The connection itself is not encrypted. **Security Profile 2** adds TLS with a server-side certificate. The charger verifies the CPMS identity via the TLS certificate, and the WebSocket handshake includes basic auth. The connection is encrypted. **Security Profile 3** is mutual TLS (mTLS). Both the CPMS and charger present certificates and verify each other. This is the gold standard for production deployments. It requires certificate management infrastructure: issuing charger certificates, handling renewals, managing revocations. Implement **certificate management** if you target Security Profile 3. OCPP 2.0.1 includes messages for installing certificates on chargers (`InstallCertificate`), signing certificate requests (`SignCertificate`), and managing the certificate chain. The same messages also exist in OCPP 1.6 via the Security Whitepaper edition 2 extension, so a 1.6 deployment with the whitepaper enabled can use the same operational workflow. You need a certificate authority or integration with one. If you are building a [CPMS from scratch](/blog/how-to-build-a-csms), factor security profile support into your architecture decisions from the beginning. ## Step 9: How Do You Test Your Implementation? Testing an OCPP implementation against real physical chargers is necessary but deeply insufficient. Real chargers are expensive, slow to configure, limited to one or two models in your lab, and cannot simulate failure scenarios on demand. You cannot test how your CPMS handles 500 simultaneous connections with three physical chargers. **Virtual chargers** (also called OCPP simulators or emulators) are the answer. A virtual charger is a software program that behaves exactly like a real charge point from your CPMS's perspective: it opens a WebSocket connection, sends BootNotification, responds to commands, and generates realistic transaction flows. Good virtual chargers let you script specific scenarios, simulate errors, and scale to hundreds of simultaneous connections. Your testing strategy should cover several layers. **Protocol conformance testing**: does your CPMS correctly handle every message type it claims to support? Send valid messages and verify correct responses. Send invalid messages and verify correct error handling. **Concurrency testing**: connect 100 or 1,000 virtual chargers simultaneously. Start transactions on all of them. Watch for race conditions, connection leaks, and database bottlenecks. **Failure scenario testing**: simulate network drops mid-transaction, send messages out of order, delay responses beyond timeout windows, send malformed payloads. This is exactly what [OCPPLab](/) is built for. Our virtual charger platform lets you spin up configurable OCPP chargers that connect to your CPMS, run through realistic charging scenarios, and stress-test your implementation without needing a single piece of physical hardware. You can test edge cases that would be impossible or impractical to reproduce with real chargers. For a comprehensive approach to testing, see our [OCPP testing guide](/blog/ocpp-testing-guide). ## Common Implementation Mistakes After working with dozens of CPMS implementations, these are the five mistakes we see most often. **Mistake 1: Treating OCPP like a REST API.** OCPP is bidirectional. Your CPMS is not just a server that receives requests. It also initiates commands to chargers. Many developers start by handling inbound messages perfectly but struggle to build the outbound command pipeline, tracking pending commands, handling responses, and managing timeouts. **Mistake 2: Ignoring clock synchronization.** Chargers have notoriously inaccurate internal clocks. If you do not enforce clock sync through Heartbeat responses, your transaction timestamps will drift, causing billing errors and confused audit logs. Always return accurate UTC time in Heartbeat responses and reject transactions with timestamps that deviate too far from server time. **Mistake 3: Not handling offline transactions.** If your CPMS assumes messages always arrive in real time and in order, it will produce incorrect billing data when a charger reconnects after an outage and replays queued messages. Design your transaction handling to be timestamp-based, not arrival-order-based. **Mistake 4: Hardcoding for a single charger vendor.** The OCPP specification leaves room for interpretation, and different charger manufacturers implement it differently. A field that one vendor always populates might be optional and absent for another. Build defensively: validate but do not assume the presence of optional fields. **Mistake 5: Testing only the happy path.** Most implementations work fine when everything goes right. They fall apart when a charger disconnects mid-transaction, sends a duplicate StartTransaction, sends MeterValues for a transaction that has already been stopped, or sends a BootNotification with a serial number that does not match any registered charger. Test every unhappy path you can think of, and then test more. ## Frequently Asked Questions ### How long does it take to build a basic OCPP-compliant CPMS? A minimal CPMS that handles BootNotification, Heartbeat, StatusNotification, Authorize, StartTransaction, StopTransaction, and MeterValues for OCPP 1.6 typically takes an experienced backend team a matter of weeks. Adding smart charging, firmware management, OCPP 2.0.1 support, and production hardening can extend that to several months. The protocol itself is not overwhelmingly complex, but the edge cases and operational resilience requirements add significant development time. ### Should I implement OCPP 1.6 or 2.0.1 first? Start with [OCPP 1.6](/blog/ocpp-1-6-vs-2-0-1). The majority of deployed chargers still speak 1.6, and it is a simpler starting point. Design your architecture to support both versions from the beginning by abstracting the protocol layer, so adding 2.0.1 support later is an extension rather than a rewrite. If you are building for a specific fleet of chargers that only support 2.0.1, then start there. ### Can I use OCPP over plain HTTP instead of WebSockets? OCPP 1.6 had an older SOAP-over-HTTP variant (OCPP 1.6S), but it is effectively deprecated. OCPP 1.6 (the JSON/WebSocket variant) and OCPP 2.0.1 both require WebSockets. The persistent, bidirectional nature of WebSockets is fundamental to how OCPP works, particularly for the CPMS to send commands to chargers without the charger having to poll. See our [WebSocket guide](/blog/ocpp-websocket-guide) for a deep dive. ### How do I handle multiple charger vendors with different OCPP quirks? Build a robust validation and normalization layer between your WebSocket handler and your business logic. Validate incoming messages against the OCPP JSON schemas but be tolerant of optional fields. Log any unexpected or non-standard behavior per vendor. Over time, you may need vendor-specific adapters for known deviations, but start by building to the specification and handling deviations as exceptions rather than designing around them. ### What is the best way to test my OCPP implementation without physical chargers? Use virtual chargers that simulate real OCPP behavior over WebSocket connections. [OCPPLab](/) provides configurable virtual chargers for both OCPP 1.6 and 2.0.1 that can test your entire message handling pipeline, simulate failure scenarios, and scale-test your infrastructure. This is dramatically faster, cheaper, and more comprehensive than testing with physical hardware alone. ### Do I need to implement every message in the OCPP specification? No. The OCPP specification defines core, optional, and vendor-specific feature profiles. Start with the core profile messages that are required for basic operation: BootNotification, Heartbeat, StatusNotification, Authorize, StartTransaction, StopTransaction, and MeterValues. Add optional profiles like Smart Charging, Firmware Management, and Remote Trigger as your product requirements demand. Most chargers will function correctly as long as your CPMS supports the core profile. --- ## OCPP Message Types Reference: 1.6 and 2.0.1 Explained Source: https://ocpplab.com/blog/ocpp-message-types-complete-reference Reference guide to all OCPP 1.6 and 2.0.1 message types, including the 28 core 1.6 actions, TransactionEvent, directions, payloads, and worked examples. **Quick answer:** OCPP message types are the named actions a charge point and CSMS exchange over WebSocket in a strict request-response pattern. Every request is a `CALL`; responses are a `CALLRESULT` or `CALLERROR`. OCPP 1.6 defines 28 core actions (plus 11 in the Security Whitepaper). OCPP 2.0.1 Edition 2 defines **64 operations** and unifies transactions under `TransactionEvent`. **OCPP message types** define every interaction between a charge point and a CSMS (Charging Station Management System; OCPP 1.6: Central System). Each message type corresponds to a specific operation: authorizing a user, starting a transaction, reporting meter data, updating firmware, or configuring smart charging profiles. The [Open Charge Point Protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/), maintained by the Open Charge Alliance, specifies exactly which party initiates each message, what fields are required, and what response is expected. OCPP communication follows a strict request-response pattern over [WebSocket](/blog/ocpp-websocket-guide). Every request is a `CALL` message containing an action name and payload. The receiver responds with either a `CALLRESULT` (success) or a `CALLERROR` (failure). There are no unsolicited responses, no partial acknowledgments, and no message queuing within the protocol itself. Understanding the full catalog of message types is the foundation for building any OCPP-compliant system. This reference covers every message type in OCPP 1.6 and 2.0.1, organized by direction and protocol version. If you want version-specific execution guidance beyond the message catalog, see [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). ## How Is an OCPP Message Formatted? All OCPP messages are JSON arrays transmitted over WebSocket. There are three message types, each identified by a `MessageTypeId` integer. ### CALL (Request) — MessageTypeId 2 ```json [2, "uniqueId-123", "BootNotification", { "chargePointVendor": "OCPPLab", "chargePointModel": "Emulator-v1" }] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `2` for CALL | | 1 | `UniqueId` | String | Unique identifier for this request (max 36 chars) | | 2 | `Action` | String | The message type name (e.g., `BootNotification`) | | 3 | `Payload` | Object | JSON object containing the message fields | ### CALLRESULT (Success Response) — MessageTypeId 3 ```json [3, "uniqueId-123", { "currentTime": "2025-03-20T10:00:00.000Z", "interval": 300, "status": "Accepted" }] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `3` for CALLRESULT | | 1 | `UniqueId` | String | Must match the `UniqueId` of the original CALL | | 2 | `Payload` | Object | Response data specific to the action | ### CALLERROR (Error Response) — MessageTypeId 4 ```json [4, "uniqueId-123", "InternalError", "Database connection timeout", {"retryAfter": 30}] ``` | Position | Field | Type | Description | |----------|-------|------|-------------| | 0 | `MessageTypeId` | Integer | Always `4` for CALLERROR | | 1 | `UniqueId` | String | Must match the `UniqueId` of the original CALL | | 2 | `ErrorCode` | String | Standardized [OCPP error code](/blog/ocpp-error-codes-reference) | | 3 | `ErrorDescription` | String | Human-readable explanation (max 255 chars) | | 4 | `ErrorDetails` | Object | Optional additional context | The `UniqueId` ties every response to its request. A charge point or CPMS must never send a CALLRESULT or CALLERROR without a matching pending CALL. If a response is not received within the configured timeout, the sender should treat the request as failed. ## Which OCPP 1.6 Messages Are Charger-Initiated? These messages are sent **from the charge point to the CPMS**. The charge point creates the CALL; the CPMS responds with CALLRESULT or CALLERROR. | Message Name | Purpose | Key Fields | When Sent | |---|---|---|---| | **Authorize** | Validate an ID tag before or during charging | `idTag` | User presents RFID card or app credential | | **BootNotification** | Register the charger and receive configuration | `chargePointVendor`, `chargePointModel`, `chargePointSerialNumber` | On startup, after reset, or after reconnection | | **DataTransfer** | Send vendor-specific data outside the standard spec | `vendorId`, `messageId`, `data` | Anytime — used for custom extensions | | **DiagnosticsStatusNotification** | Report diagnostic upload progress | `status` (Idle, Uploaded, UploadFailed, Uploading) | After CPMS requests diagnostics via GetDiagnostics | | **FirmwareStatusNotification** | Report firmware update progress | `status` (Downloaded, DownloadFailed, Downloading, Idle, InstallationFailed, Installing, Installed) | During firmware update lifecycle | | **Heartbeat** | Confirm the charger is still connected | *(empty payload)* | At the interval specified in BootNotification response | | **MeterValues** | Report energy measurements and power readings | `connectorId`, `meterValue[]` (timestamp, sampledValue[]) | Periodically during charging, or clock-aligned | | **StartTransaction** | Notify CPMS that a charging session has begun | `connectorId`, `idTag`, `meterStart`, `timestamp` | When energy transfer starts | | **StatusNotification** | Report the current status of a connector | `connectorId`, `errorCode`, `status` | On status change (Available, Charging, Faulted, etc.) | | **StopTransaction** | Notify CPMS that a charging session has ended | `transactionId`, `meterStop`, `timestamp`, `reason` | When energy transfer stops | Every charger-initiated message expects a `.conf` response from the CPMS. For example, `BootNotification` expects a `BootNotification.conf` containing `status`, `currentTime`, and `interval`. If the CPMS responds with `status: Rejected`, the charger must retry at the interval specified and must not accept charging sessions until accepted. ## Which OCPP 1.6 Messages Are CPMS-Initiated? These messages are sent **from the CPMS to the charge point**. The CPMS creates the CALL; the charge point responds. | Message Name | Purpose | Key Fields | When Sent | |---|---|---|---| | **CancelReservation** | Cancel a previously made reservation | `reservationId` | When a user cancels or reservation policy requires it | | **ChangeAvailability** | Set a connector or charger to operative/inoperative | `connectorId`, `type` (Operative, Inoperative) | For maintenance, scheduling, or load management | | **ChangeConfiguration** | Update a configuration key on the charger | `key`, `value` | To adjust settings like heartbeat interval or meter sampling | | **ClearCache** | Clear the charger's local authorization cache | *(empty payload)* | When authorization data has changed centrally | | **ClearChargingProfile** | Remove one or more charging profiles | `id`, `connectorId`, `chargingProfilePurpose`, `stackLevel` | When smart charging profiles need to be cleared | | **DataTransfer** | Send vendor-specific data to the charger | `vendorId`, `messageId`, `data` | For custom vendor extensions | | **GetCompositeSchedule** | Retrieve the effective composite charging schedule from all active profiles | `connectorId`, `duration`, `chargingRateUnit` | For verifying the actual schedule a connector will follow | | **GetConfiguration** | Retrieve current configuration values | `key[]` (optional — omit to get all) | For diagnostics or auditing charger settings | | **GetDiagnostics** | Request the charger to upload diagnostic logs | `location` (URI), `startTime`, `stopTime`, `retries` | When debugging charger issues remotely | | **GetLocalListVersion** | Check the version of the local authorization list | *(empty payload)* | Before sending an updated local list | | **RemoteStartTransaction** | Remotely start a charging session | `idTag`, `connectorId` (optional), `chargingProfile` (optional) | When user starts charging via mobile app or CPMS portal | | **RemoteStopTransaction** | Remotely stop a charging session | `transactionId` | When user or operator stops charging remotely | | **ReserveNow** | Reserve a connector for a specific user | `connectorId`, `expiryDate`, `idTag`, `reservationId` | When a user reserves a charger in advance | | **Reset** | Reboot the charger | `type` (Hard, Soft) | For recovery, updates, or maintenance | | **SendLocalList** | Send or update the local authorization list | `listVersion`, `localAuthorizationList[]`, `updateType` | To enable offline authorization | | **SetChargingProfile** | Install a charging profile for smart charging | `connectorId`, `csChargingProfiles` | For load balancing, demand response, or scheduled charging | | **TriggerMessage** | Request the charger to send a specific message immediately | `requestedMessage` (e.g., BootNotification, MeterValues) | When CPMS needs a status update on demand | | **UnlockConnector** | Remotely unlock a connector | `connectorId` | When a cable is stuck or user requests remote unlock | | **UpdateFirmware** | Instruct charger to download and install new firmware | `location` (URI), `retrieveDate`, `retries`, `retryInterval` | For firmware rollouts | All 19 CPMS-initiated messages follow the same CALL/CALLRESULT pattern. The charge point must implement handlers for every message it claims to support in its feature profile. ## What Messages Are New in OCPP 2.0.1? [OCPP 2.0.1](/blog/ocpp-1-6-vs-2-0-1) introduces a significantly expanded message set organized into functional blocks, as documented in the [OCPP 2.0.1 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) from the Open Charge Alliance. Many OCPP 1.6 messages were renamed, split, or consolidated. The following table lists messages that are **new in 2.0.1** or substantially changed from 1.6. ### New Charger-Initiated Messages (2.0.1) | Message Name | Purpose | Functional Block | |---|---|---| | **Authorize** | Extended with certificate-based auth, ISO 15118 support | Authorization | | **ClearedChargingLimit** | Notify CPMS that an external charging limit was cleared | SmartCharging | | **FirmwareStatusNotification** | Extended with `requestId` for tracking | FirmwareManagement | | **Get15118EVCertificate** | Request an ISO 15118 certificate for the EV | ISO15118CertificateManagement | | **LogStatusNotification** | Report log upload status (replaces DiagnosticsStatusNotification) | Diagnostics | | **MeterValues** | Restructured with `evse` instead of `connectorId` | MeterValues | | **NotifyChargingLimit** | Report external charging limits (e.g., from grid operator) | SmartCharging | | **NotifyCustomerInformation** | Return customer information requested by CPMS | CustomerInformation | | **NotifyDisplayMessages** | Return display messages currently stored | DisplayMessage | | **NotifyEVChargingNeeds** | Report the EV's charging requirements (ISO 15118) | SmartCharging | | **NotifyEVChargingSchedule** | Report the current EV charging schedule | SmartCharging | | **NotifyEvent** | Report events and monitoring results | DeviceModel | | **NotifyMonitoringReport** | Return monitoring configuration data | DeviceModel | | **NotifyReport** | Return device model report data | DeviceModel | | **PublishFirmwareStatusNotification** | Report publish firmware status for local controller | FirmwareManagement | | **ReportChargingProfiles** | Return installed charging profiles | SmartCharging | | **ReservationStatusUpdate** | Report reservation status changes | Reservation | | **SecurityEventNotification** | Report security-related events | Security | | **SignCertificate** | Request CPMS to sign a certificate | Security | | **TransactionEvent** | Unified transaction lifecycle reporting (replaces StartTransaction, StopTransaction, MeterValues during transaction) | Transactions | ### New CPMS-Initiated Messages (2.0.1) | Message Name | Purpose | Functional Block | |---|---|---| | **CertificateSigned** | Send a signed certificate to the charger | Security | | **ClearDisplayMessage** | Remove a message from the charger display | DisplayMessage | | **ClearVariableMonitoring** | Remove monitoring settings | DeviceModel | | **CostUpdated** | Update the running cost of a transaction | TariffAndCost | | **CustomerInformation** | Request customer data stored on charger | CustomerInformation | | **DeleteCertificate** | Remove an installed certificate | Security | | **GetBaseReport** | Request a full device model report | DeviceModel | | **GetChargingProfiles** | Request installed charging profiles | SmartCharging | | **GetDisplayMessages** | Request current display messages | DisplayMessage | | **GetInstalledCertificateIds** | List installed certificates | Security | | **GetLog** | Request log upload (replaces GetDiagnostics) | Diagnostics | | **GetMonitoringReport** | Request monitoring configuration | DeviceModel | | **GetReport** | Request specific device model variables | DeviceModel | | **GetTransactionStatus** | Check if a transaction is still ongoing | Transactions | | **GetVariables** | Read device model variables | DeviceModel | | **InstallCertificate** | Install a certificate on the charger | Security | | **PublishFirmware** | Instruct local controller to publish firmware | FirmwareManagement | | **RequestStartTransaction** | Start a transaction (replaces RemoteStartTransaction) | Transactions | | **RequestStopTransaction** | Stop a transaction (replaces RemoteStopTransaction) | Transactions | | **SetDisplayMessage** | Configure a message on the charger display | DisplayMessage | | **SetMonitoringBase** | Configure monitoring base settings | DeviceModel | | **SetMonitoringLevel** | Set the severity level for monitoring | DeviceModel | | **SetNetworkProfile** | Configure network connection settings | Provisioning | | **SetVariableMonitoring** | Configure monitoring on device variables | DeviceModel | | **SetVariables** | Write device model variables | DeviceModel | | **UnpublishFirmware** | Remove published firmware from local controller | FirmwareManagement | The most significant architectural change in 2.0.1 is the introduction of **TransactionEvent**, which consolidates `StartTransaction`, `StopTransaction`, and in-transaction `MeterValues` into a single message with an `eventType` field (`Started`, `Updated`, `Ended`). This simplifies transaction tracking and eliminates race conditions common in 1.6 implementations. ## Key Messages Deep Dive The following sections provide detailed request/response examples for the six most commonly implemented and debugged OCPP messages. ### BootNotification BootNotification is the first meaningful message a charger sends after establishing a WebSocket connection. It registers the charger with the CPMS and receives time synchronization and heartbeat configuration. **OCPP 1.6 Request:** ```json [2, "boot-001", "BootNotification", { "chargePointVendor": "OCPPLab", "chargePointModel": "Emulator-Pro", "chargePointSerialNumber": "OCPPLAB-001-2025", "chargeBoxSerialNumber": "CB-001", "firmwareVersion": "2.5.0", "iccid": "8901260882902730001", "imsi": "310260000000001", "meterType": "ACMeter", "meterSerialNumber": "MTR-001" }] ``` **OCPP 1.6 Response (Accepted):** ```json [3, "boot-001", { "currentTime": "2025-03-20T10:00:00.000Z", "interval": 300, "status": "Accepted" }] ``` **OCPP 2.0.1 Request** (restructured with nested `chargingStation` object): ```json [2, "boot-001", "BootNotification", { "reason": "PowerUp", "chargingStation": { "model": "Emulator-Pro", "vendorName": "OCPPLab", "serialNumber": "OCPPLAB-001-2025", "firmwareVersion": "2.5.0" } }] ``` The `status` field in the response determines charger behavior: - **Accepted**: Charger operates normally, sends Heartbeat at the specified `interval`. - **Pending**: CPMS needs more time or configuration. Charger must not accept transactions. Retry at `interval`. - **Rejected**: Charger is not recognized. Charger must not accept transactions. Retry at `interval`. A charger stuck in `Pending` or `Rejected` is one of the most common deployment issues. Check the serial number, vendor name, and CPMS registration status when troubleshooting. ### StartTransaction vs. TransactionEvent In OCPP 1.6, `StartTransaction` and `StopTransaction` are separate messages. In 2.0.1, both are replaced by `TransactionEvent`. **OCPP 1.6 StartTransaction:** ```json [2, "tx-001", "StartTransaction", { "connectorId": 1, "idTag": "RFID-ABC123", "meterStart": 1500, "timestamp": "2025-03-20T10:05:00.000Z" }] ``` **OCPP 1.6 StartTransaction Response:** ```json [3, "tx-001", { "idTagInfo": { "status": "Accepted", "expiryDate": "2025-12-31T23:59:59.000Z" }, "transactionId": 42 }] ``` **OCPP 2.0.1 TransactionEvent (Started):** ```json [2, "tx-001", "TransactionEvent", { "eventType": "Started", "timestamp": "2025-03-20T10:05:00.000Z", "triggerReason": "Authorized", "seqNo": 0, "transactionInfo": { "transactionId": "TX-20250320-001" }, "idToken": { "idToken": "RFID-ABC123", "type": "ISO14443" }, "evse": { "id": 1, "connectorId": 1 } }] ``` **OCPP 2.0.1 TransactionEvent (Ended):** ```json [2, "tx-002", "TransactionEvent", { "eventType": "Ended", "timestamp": "2025-03-20T12:30:00.000Z", "triggerReason": "EVDeparted", "seqNo": 15, "transactionInfo": { "transactionId": "TX-20250320-001", "stoppedReason": "EVDisconnected" }, "meterValue": [{ "timestamp": "2025-03-20T12:30:00.000Z", "sampledValue": [{ "value": 32.5, "measurand": "Energy.Active.Import.Register", "unitOfMeasure": { "unit": "kWh" } }] }] }] ``` Key differences: In 2.0.1, the transaction ID is a string generated by the charger (not an integer assigned by the CPMS). Meter values can be included directly in `TransactionEvent` messages, reducing the number of separate `MeterValues` calls needed during a session. ### MeterValues MeterValues reports energy consumption, power levels, voltage, current, and other electrical measurements during a charging session. It is one of the highest-frequency messages in any OCPP deployment. **OCPP 1.6 MeterValues:** ```json [2, "meter-001", "MeterValues", { "connectorId": 1, "transactionId": 42, "meterValue": [{ "timestamp": "2025-03-20T10:15:00.000Z", "sampledValue": [ { "value": "1.85", "context": "Sample.Periodic", "format": "Raw", "measurand": "Energy.Active.Import.Register", "location": "Outlet", "unit": "kWh" }, { "value": "7200", "context": "Sample.Periodic", "measurand": "Power.Active.Import", "unit": "W" }, { "value": "230.1", "context": "Sample.Periodic", "measurand": "Voltage", "unit": "V" }, { "value": "31.3", "context": "Sample.Periodic", "measurand": "Current.Import", "unit": "A" } ] }] }] ``` **Sampling contexts determine when meter values are captured:** | Context | Description | |---|---| | `Sample.Periodic` | Taken at a regular interval configured via `MeterValueSampleInterval` | | `Sample.Clock` | Taken at clock-aligned intervals configured via `ClockAlignedDataInterval` | | `Transaction.Begin` | Taken at the start of a transaction | | `Transaction.End` | Taken at the end of a transaction | | `Trigger` | Taken in response to a TriggerMessage request | | `Interruption.Begin` | Taken when power delivery is interrupted | | `Interruption.End` | Taken when power delivery resumes | | `Other` | Any reading not covered by the other contexts | **Sampled vs. Clock-Aligned**: `Sample.Periodic` values are relative to the transaction start (e.g., every 60 seconds after charging begins). `Sample.Clock` values align to absolute clock boundaries (e.g., every 15 minutes on the hour: 10:00, 10:15, 10:30). Clock-aligned data is typically used for billing and regulatory reporting because it produces consistent time boundaries across all chargers. The CPMS response to MeterValues is always an empty object `{}`. There is no mechanism for the CPMS to reject or request retransmission of meter data within the protocol. ### StatusNotification StatusNotification reports the operational state of a connector or the charge point itself. It is sent whenever a state transition occurs. **OCPP 1.6 StatusNotification:** ```json [2, "status-001", "StatusNotification", { "connectorId": 1, "errorCode": "NoError", "status": "Charging", "timestamp": "2025-03-20T10:05:01.000Z", "info": "Vehicle connected and charging at 7.2kW", "vendorId": "OCPPLab", "vendorErrorCode": "" }] ``` **OCPP 1.6 Status Values:** | Status | Description | |---|---| | `Available` | Connector is free and ready for a new session | | `Preparing` | Connector is occupied but not yet charging (e.g., cable plugged in, awaiting authorization) | | `Charging` | Energy is actively being transferred to the EV | | `SuspendedEVSE` | Charging paused by the charger (e.g., load balancing, temperature limit) | | `SuspendedEV` | Charging paused by the vehicle (e.g., battery management, target SoC reached temporarily) | | `Finishing` | Transaction is stopping, energy transfer has ceased, connector not yet available | | `Reserved` | Connector is reserved for a specific user | | `Unavailable` | Connector is not available for charging (maintenance, out of service) | | `Faulted` | Connector has a fault condition — check `errorCode` for specifics | **OCPP 1.6 Error Codes in StatusNotification:** | Error Code | Description | |---|---| | `ConnectorLockFailure` | Failed to lock or unlock the connector | | `EVCommunicationError` | Communication failure with the vehicle | | `GroundFailure` | Ground fault detected | | `HighTemperature` | Temperature exceeded safe limits | | `InternalError` | Internal charger error | | `LocalListConflict` | Conflict in local authorization list | | `NoError` | No error (normal operation) | | `OtherError` | Error not covered by other codes | | `OverCurrentFailure` | Overcurrent detected | | `OverVoltage` | Voltage exceeded safe limits | | `PowerMeterFailure` | Power meter communication failure | | `PowerSwitchFailure` | Power relay or switch failure | | `ReaderFailure` | RFID reader or authorization device failure | | `ResetFailure` | Charger failed to reset | | `UnderVoltage` | Voltage below minimum safe level | | `WeakSignal` | Cellular or wireless signal too weak | In OCPP 2.0.1, `StatusNotification` is simplified to report only `connectorStatus` (`Available`, `Occupied`, `Reserved`, `Unavailable`, `Faulted`). Detailed error reporting moves to the `NotifyEvent` message and the device model. ### SetChargingProfile SetChargingProfile installs a charging profile on a connector for smart charging, load balancing, or demand response. It is the foundation of [smart charging](/blog/smart-charging-explained) in OCPP. **OCPP 1.6 SetChargingProfile (load limiting to 16A):** ```json [2, "profile-001", "SetChargingProfile", { "connectorId": 1, "csChargingProfiles": { "chargingProfileId": 100, "stackLevel": 0, "chargingProfilePurpose": "TxDefaultProfile", "chargingProfileKind": "Absolute", "chargingSchedule": { "chargingRateUnit": "A", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 16.0 } ] } } }] ``` **Time-of-use smart charging example (OCPP 1.6, off-peak boost).** OCPP 2.0.1 uses `ChargingStationMaxProfile` instead of `ChargePointMaxProfile`, and targets an EVSE rather than `connectorId: 0` for the station-wide limit: ```json [2, "profile-002", "SetChargingProfile", { "connectorId": 0, "csChargingProfiles": { "chargingProfileId": 200, "stackLevel": 1, "chargingProfilePurpose": "ChargePointMaxProfile", "chargingProfileKind": "Recurring", "recurrencyKind": "Daily", "chargingSchedule": { "startSchedule": "2025-03-20T00:00:00.000Z", "chargingRateUnit": "A", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 16.0 }, { "startPeriod": 25200, "limit": 8.0 }, { "startPeriod": 72000, "limit": 32.0 } ] } } }] ``` This profile limits the entire charge point (`connectorId: 0`) to 16A from midnight, reduces to 8A at 07:00 (peak hours, `startPeriod: 25200` = 7 hours x 3600 seconds), and boosts to 32A at 20:00 (`startPeriod: 72000` = 20 hours x 3600 seconds) during off-peak. **Charging profile purposes (OCPP 1.6):** - **ChargePointMaxProfile**: Maximum power for the entire charge point. Applied to `connectorId: 0`. - **TxDefaultProfile**: Default profile applied to all transactions on a connector unless overridden. - **TxProfile**: Profile for a specific active transaction. Highest priority for that transaction. **Charging profile purposes (OCPP 2.0.1):** `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, `TxDefaultProfile`, `TxProfile`. There is no `ChargePointMaxProfile` in 2.0.1. Profiles at higher `stackLevel` values take precedence when multiple profiles of the same purpose exist. The effective limit is always the minimum of all applicable profiles. ### RemoteStartTransaction RemoteStartTransaction instructs a charger to begin a charging session, typically triggered by a mobile app or backend system. It can optionally include a charging profile for the session. **OCPP 1.6 RemoteStartTransaction:** ```json [2, "remote-001", "RemoteStartTransaction", { "connectorId": 1, "idTag": "APP-USER-456", "chargingProfile": { "chargingProfileId": 300, "stackLevel": 0, "chargingProfilePurpose": "TxProfile", "chargingProfileKind": "Absolute", "chargingSchedule": { "chargingRateUnit": "W", "chargingSchedulePeriod": [ { "startPeriod": 0, "limit": 7400.0 }, { "startPeriod": 7200, "limit": 11000.0 } ] } } }] ``` **Response:** ```json [3, "remote-001", { "status": "Accepted" }] ``` This request starts a session on connector 1 for user `APP-USER-456`, beginning at 7.4 kW and increasing to 11 kW after 2 hours. The charger will respond `Accepted` if it can start the session, or `Rejected` if the connector is unavailable, faulted, or occupied. After accepting a `RemoteStartTransaction`, the charger must still send a `StartTransaction` message to the CPMS once energy transfer actually begins. The `RemoteStartTransaction` acceptance only means the charger will attempt to start; it does not guarantee the session will begin (the EV may not be plugged in, authorization may fail, etc.). In OCPP 2.0.1, this message is renamed to `RequestStartTransaction` and includes an `evseId` instead of `connectorId`, along with an optional `groupIdToken` for group authorization scenarios. ## How Should You Handle OCPP Errors? When a CALL message cannot be processed, the receiver sends a CALLERROR instead of a CALLRESULT. OCPP defines these standard [error codes](/blog/ocpp-error-codes-reference): | Error Code | Description | |---|---| | `NotImplemented` | The action is not supported by the receiver | | `NotSupported` | The action is recognized but not supported in this context | | `InternalError` | An internal error prevented processing | | `ProtocolError` | The message does not conform to the OCPP protocol | | `SecurityError` | A security violation was detected | | `FormationViolation` | The payload is syntactically incorrect (malformed JSON, wrong types) | | `PropertyConstraintViolation` | A field value violates its constraints (e.g., string too long, number out of range) | | `OccurrenceConstraintViolation` | A required field is missing or an unexpected field is present | | `TypeConstraintViolation` | A field has the wrong data type | | `GenericError` | Any error not covered by the above codes | Best practices for error handling: 1. **Always respond.** Never leave a CALL unanswered. If you cannot process it, send a CALLERROR. 2. **Use specific error codes.** `FormationViolation` is more useful than `GenericError` when the JSON is malformed. 3. **Include error details.** The `errorDetails` object should contain actionable information such as which field failed validation and why. 4. **Implement timeouts.** If no response arrives within 30 seconds (configurable), treat the request as failed and clean up any pending state. 5. **Log everything.** Every CALLERROR should be logged with the full request context for debugging. ## Frequently Asked Questions ### How many message types does OCPP 1.6 define? As enumerated in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) published by the Open Charge Alliance (first released in 2015), the core profile defines 28 unique actions: 10 charger-initiated and 19 CPMS-initiated, with `DataTransfer` appearing in both directions. Each action has a corresponding `.conf` response structure, but these are not counted as separate messages. The [OCPP 1.6 Security Whitepaper](https://openchargealliance.org/ocpp-info-whitepapers/ocpp-1-6-security-whitepaper-4th-edition/), whose security extension was introduced in edition 2, adds 11 more actions (signed firmware, certificate management, log upload, and `SecurityEventNotification`), bringing the full count to roughly 39 when both the core and the security extension are implemented. ### What changed from OCPP 1.6 to OCPP 2.0.1 regarding messages? OCPP 2.0.1 roughly doubles the message count and reorganizes them into functional blocks. The most impactful change is replacing `StartTransaction`, `StopTransaction`, and in-transaction `MeterValues` with the unified `TransactionEvent` message. New functional areas include security certificate management, display messaging, device model reporting, and ISO 15118 support. See our detailed [comparison guide](/blog/ocpp-1-6-vs-2-0-1). ### Can I use DataTransfer for anything? `DataTransfer` is the escape hatch for vendor-specific functionality not covered by the standard. Both the charger and CPMS can initiate it. Common uses include custom diagnostics, proprietary load management, and feature flags. However, relying heavily on DataTransfer reduces interoperability because each vendor's payloads are different. ### What happens if the charger sends a message the CPMS does not support? The CPMS should respond with a CALLERROR using `NotImplemented` as the error code. The charger must handle this gracefully. For critical messages like `BootNotification`, this typically indicates a serious configuration or version mismatch. ### How do I test all these message types? Use an [OCPP emulator](/blog/introducing-ocpp-emulator) to simulate both charger and CPMS behavior. A good emulator lets you send any message type with custom payloads, inspect responses, and test error scenarios without physical hardware. This is essential for validating your implementation against the full spec before deploying to production chargers. ### Are there differences between OCPP-J and OCPP-S message types? The message types (actions) are identical between OCPP-J (JSON over WebSocket) and OCPP-S (SOAP over HTTP). The difference is the transport format: OCPP-J uses the JSON array format described in this guide, while OCPP-S wraps the same data in XML/SOAP envelopes. OCPP-J is the dominant implementation today, and OCPP 2.0.1 only supports JSON. Read our [WebSocket guide](/blog/ocpp-websocket-guide) for transport-level details. ## What's Next This reference covers the message catalog. For implementation, start with these focused guides: - **[What is OCPP?](/blog/what-is-ocpp)** — Protocol fundamentals and architecture overview - **[OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1)** — Detailed version comparison and migration guidance - **[OCPP WebSocket Guide](/blog/ocpp-websocket-guide)** — Connection lifecycle, security, and reconnection strategies - **[OCPP Error Codes Reference](/blog/ocpp-error-codes-reference)** — Deep dive into every error code with troubleshooting - **[Smart Charging Explained](/blog/smart-charging-explained)** — Charging profiles, load management, and demand response --- ## OCPI Endpoints Reference: API Guide for 2.1.1 and 2.2.1 Source: https://ocpplab.com/blog/ocpi-endpoints-complete-reference Complete OCPI endpoint reference for versions 2.1.1 and 2.2.1, covering all 9 modules with methods, payloads, party ownership, and implementation notes. **Quick answer:** OCPI is a REST API where every endpoint is discovered dynamically through the versions endpoint. This reference documents all module endpoints — Locations, Sessions, CDRs, Tariffs, Tokens, Commands, plus the 2.2.1-only ChargingProfiles and HubClientInfo — covering methods, payloads, party ownership, and implementation notes for versions 2.1.1 and 2.2.1. OCPI -- the [Open Charge Point Interface](https://github.com/ocpi/ocpi) maintained by the EV Roaming Foundation -- is a REST API protocol. Every interaction between a [CPO and an eMSP](/blog/cpo-vs-emsp-explained) -- or between either party and a roaming hub like [GIREVE](/blog/gireve-hub-integration) -- is a standard HTTP request carrying a JSON payload. There are no WebSocket connections, no binary frames, no persistent channels. If you understand REST, you understand the transport layer of OCPI. What makes OCPI distinct is its module-based architecture: each functional domain (locations, sessions, billing, authorization) has its own set of endpoints with clearly defined ownership between parties. This reference covers every endpoint across all OCPI modules for versions 2.1.1 and 2.2.1. For each module, you will find the purpose, which party implements which endpoints, the full endpoint table, key data fields, and implementation notes. If you are new to [OCPI as a protocol](/blog/what-is-ocpi), start there first. This document assumes you understand the basics and need the endpoint-level detail. For version-specific implementation validation, pair this reference with [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) and [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1). ## How Are OCPI Base URLs Structured and Versioned? Every OCPI implementation exposes a single entry point: the versions endpoint. From there, all module endpoints are discovered dynamically. There are no hardcoded paths. The base URL structure follows this pattern: ``` https://api.example.com/ocpi/ ``` From this root, the protocol defines two discovery endpoints that every implementation must support: - `GET /versions` -- returns a list of supported OCPI versions with their URLs - `GET /versions/{version_id}` -- returns the list of module endpoints for a specific version A typical versions response looks like this: ```json { "status_code": 1000, "data": [ { "version": "2.1.1", "url": "https://api.example.com/ocpi/2.1.1" }, { "version": "2.2.1", "url": "https://api.example.com/ocpi/2.2.1" } ] } ``` When you call the version-specific URL, you receive the full list of module endpoints that party supports: ```json { "status_code": 1000, "data": { "version": "2.1.1", "endpoints": [ { "identifier": "credentials", "url": "https://api.example.com/ocpi/2.1.1/credentials" }, { "identifier": "locations", "url": "https://api.example.com/ocpi/2.1.1/locations" }, { "identifier": "sessions", "url": "https://api.example.com/ocpi/2.1.1/sessions" }, { "identifier": "cdrs", "url": "https://api.example.com/ocpi/2.1.1/cdrs" }, { "identifier": "tariffs", "url": "https://api.example.com/ocpi/2.1.1/tariffs" }, { "identifier": "tokens", "url": "https://api.example.com/ocpi/2.1.1/tokens" }, { "identifier": "commands", "url": "https://api.example.com/ocpi/2.1.1/commands" } ] } } ``` This dynamic discovery is a core design principle. You never assume where a module lives. You always discover it through the version endpoint. This allows implementations to host modules on different servers, use different URL structures, or version independently. ## How Does the OCPI Credentials Handshake Work? OCPI uses token-based authentication. Every HTTP request includes an `Authorization` header with a `Token` prefix: ``` Authorization: Token IpbJOXxkxOAuKR92z0nEcmVF3Qc09VG7I7d/WCg0koM= ``` These tokens are not JWTs. They are opaque strings, typically base64-encoded random bytes. The critical aspect is how they are exchanged: through the credentials handshake. ### The Credentials Exchange Flow The credentials module is the only module that uses a pre-shared token (TOKEN_A) for initial authentication. OCPI **2.1.1** uses a Token A → Token B model (each side ends up with one credentials token). OCPI **2.2.1** introduces a third token (Token C) for hub-aware routing. The 2.1.1 flow: **Step 1**: Out-of-band, Party A and Party B agree on a TOKEN_A. This is typically exchanged via email, a hub's admin portal, or a registration API. **Step 2**: Party A calls `GET /versions` on Party B's platform, authenticating with TOKEN_A, to discover supported versions. **Step 3**: Party A calls `GET /versions/2.1.1` (or whichever version both support) to discover Party B's module endpoints. **Step 4**: Party A sends `POST /credentials` to Party B, including: - Party A's own credentials URL (its `/versions` endpoint) - A new token Party A generated for Party B to use when calling Party A - Party A's business details (`party_id`, `country_code`, `business_details`, `roles`) **Step 5**: Party B validates the request using TOKEN_A, stores the token from the body, and responds with its own credentials object — including the token Party A will use to call Party B going forward (commonly called TOKEN_B). From this point forward, TOKEN_A is invalidated. Party A uses the token from Step 5 to authenticate requests to Party B. Party B uses the token from Step 4 to authenticate requests to Party A. > **OCPI 2.2.1 note:** The hub-aware variant of this handshake adds TOKEN_C — a third token the hub uses to route between parties. The mechanics are otherwise the same. ### Credentials Module Endpoints | Method | Path | Description | Used By | |--------|------|-------------|---------| | GET | `/credentials` | Retrieve the credentials object of the other party | Both | | POST | `/credentials` | Register with the other party (initial handshake) | Both | | PUT | `/credentials` | Update credentials (token rotation) | Both | | DELETE | `/credentials` | Unregister from the other party | Both | The `PUT /credentials` endpoint allows either party to rotate tokens at any time without disrupting the connection. This is a significant security advantage and should be done periodically in production deployments. ## What Does the Locations Module Do? The Locations module is the backbone of OCPI. It contains the complete inventory of charge points, their physical locations, capabilities, and real-time status. Every roaming connection starts with location data exchange. OCPI uses a three-level hierarchy: **Location** (a physical site) contains one or more **EVSEs** (individual charge points), each of which has one or more **Connectors** (physical sockets). **Implemented by**: CPO (sender/owner of location data), eMSP (receiver) ### CPO Endpoints (Sender Interface) These endpoints are implemented by the CPO. The eMSP calls them to pull location data. | Method | Path | Description | |--------|------|-------------| | GET | `/locations` | Fetch list of all locations (paginated, supports `date_from`/`date_to` filtering) | | GET | `/locations/{location_id}` | Fetch a specific location with all EVSEs and connectors | | GET | `/locations/{location_id}/{evse_uid}` | Fetch a specific EVSE | | GET | `/locations/{location_id}/{evse_uid}/{connector_id}` | Fetch a specific connector | ### eMSP Endpoints (Receiver Interface) These endpoints are implemented by the eMSP. The CPO calls them to push location updates. | Method | Path | Description | |--------|------|-------------| | PUT | `/locations/{country_code}/{party_id}/{location_id}` | Push a full location object (create or replace) | | PUT | `/locations/{country_code}/{party_id}/{location_id}/{evse_uid}` | Push a full EVSE object | | PUT | `/locations/{country_code}/{party_id}/{location_id}/{evse_uid}/{connector_id}` | Push a full connector object | | PATCH | `/locations/{country_code}/{party_id}/{location_id}` | Partial update to a location | | PATCH | `/locations/{country_code}/{party_id}/{location_id}/{evse_uid}` | Partial update to an EVSE | | PATCH | `/locations/{country_code}/{party_id}/{location_id}/{evse_uid}/{connector_id}` | Partial update to a connector | ### Key Location Data Fields | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique identifier of the location within the CPO's platform | | `type` | LocationType | ON_STREET, PARKING_GARAGE, UNDERGROUND_GARAGE, PARKING_LOT, OTHER | | `address` | string | Street address | | `city` | string | City name | | `coordinates` | GeoLocation | Latitude and longitude | | `evses` | EVSE[] | List of EVSEs at this location | | `operator` | BusinessDetails | Operator information (name, website, logo) | | `time_zone` | string | IANA time zone identifier (2.2.1 only) | | `last_updated` | DateTime | Timestamp of the last update | ### Key EVSE Data Fields | Field | Type | Description | |-------|------|-------------| | `uid` | string | Unique identifier within the CPO's platform | | `evse_id` | string | Compliant EVSE ID following the standard format (e.g., DE*CPO*E12345) | | `status` | Status | AVAILABLE, BLOCKED, CHARGING, INOPERATIVE, OUTOFORDER, PLANNED, REMOVED, RESERVED, UNKNOWN | | `connectors` | Connector[] | List of connectors on this EVSE | | `capabilities` | Capability[] | CHARGING_PROFILE_CAPABLE, REMOTE_START_STOP_CAPABLE, RFID_READER, etc. | | `last_updated` | DateTime | Timestamp of the last update | ### Push vs Pull for Locations In production, CPOs push EVSE status changes in real-time using `PATCH` requests. The eMSP uses `GET /locations` with `date_from` filtering for periodic full synchronization -- typically daily or weekly -- to catch any missed push updates. When a CPO sends a PATCH, it should include only the changed fields. A common implementation error is sending full objects via PATCH instead of partial updates, which defeats the purpose of the method. ## How Does the Sessions Module Track Charging? The Sessions module tracks active charging sessions in near-real-time. An eMSP uses session data to show drivers the status of their ongoing charge, including energy delivered, duration, and estimated cost. **Implemented by**: CPO (sender/owner of session data), eMSP (receiver) ### CPO Endpoints (Sender Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/sessions` | Fetch list of sessions (paginated, supports `date_from`/`date_to`) | | GET | `/sessions/{session_id}` | Fetch a specific session (2.1.1 only) | ### eMSP Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | PUT | `/sessions/{country_code}/{party_id}/{session_id}` | Push a full session object (create or replace) | | PATCH | `/sessions/{country_code}/{party_id}/{session_id}` | Partial update to a session (status change, energy update) | ### Key Session Data Fields | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique session identifier | | `start_datetime` | DateTime | When the session started | | `end_datetime` | DateTime | When the session ended (null if still active) | | `kwh` | number | Total energy delivered in kWh | | `auth_id` | string | Token used for authorization | | `location` | Location | Reference to the location where charging occurs | | `currency` | string | ISO 4217 currency code | | `total_cost` | number | Current total cost (updated during charging) | | `status` | SessionStatus | ACTIVE, COMPLETED, INVALID, PENDING | | `last_updated` | DateTime | Timestamp of the last update | ### Implementation Notes During an active session, the CPO should push session updates to the eMSP at regular intervals -- typically every 30 to 60 seconds. Each update includes the latest `kwh` value and `total_cost`. When the session ends, a final `PATCH` sets the `status` to `COMPLETED` and the `end_datetime`. The session object is then considered immutable. For billing, always rely on the CDR, not the final session object. ## What Are CDRs (Charge Detail Records) in OCPI? CDRs are the billing backbone of OCPI. After a charging session completes, the CPO generates a CDR containing the definitive record of what was consumed and what it costs. CDRs are immutable once created -- they cannot be updated or deleted through OCPI. **Implemented by**: CPO (sender), eMSP (receiver) ### CPO Endpoints (Sender Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/cdrs` | Fetch list of CDRs (paginated, supports `date_from`/`date_to`) | | GET | `/cdrs/{cdr_id}` | Fetch a specific CDR (2.1.1 only, removed in 2.2.1 sender interface) | ### eMSP Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | POST | `/cdrs` | Push a new CDR to the eMSP | | GET | `/cdrs/{cdr_id}` | Fetch a specific CDR by ID (2.2.1 receiver can retrieve stored CDRs) | ### Key CDR Data Fields | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique CDR identifier | | `start_date_time` | DateTime | Start of the charging session | | `end_date_time` | DateTime | End of the charging session | | `auth_id` | string | Token used for authorization | | `auth_method` | AuthMethod | AUTH_REQUEST, COMMAND, WHITELIST | | `location` | Location | Location where charging occurred | | `currency` | string | ISO 4217 currency code | | `total_cost` | number | Total cost of the session | | `total_energy` | number | Total energy delivered in kWh | | `total_time` | number | Total duration in hours | | `total_parking_time` | number | Total idle/parking time in hours | | `charging_periods` | ChargingPeriod[] | Detailed breakdown of the session into time periods with dimensions | | `last_updated` | DateTime | Timestamp of last update | ### Charging Periods and Dimensions Each CDR contains an array of `ChargingPeriod` objects, which break the session into time-based segments. Each period has a `start_date_time` and an array of `CdrDimension` objects: | Dimension Type | Description | |---------------|-------------| | `ENERGY` | Energy consumed in kWh during this period | | `FLAT` | Flat fee applied (value is always 1 when present) | | `MAX_CURRENT` | Maximum current in A during this period | | `MIN_CURRENT` | Minimum current in A during this period | | `PARKING_TIME` | Idle/parking time in hours | | `TIME` | Charging time in hours | These dimensions map directly to tariff elements, enabling precise cost calculation. If you are building a billing system, the CDR's charging periods are the source of truth for invoice generation. ## Tariffs Module The Tariffs module defines pricing structures for charging sessions. CPOs publish their tariffs so eMSPs can display estimated costs to drivers before they start charging. **Implemented by**: CPO (sender), eMSP (receiver) ### CPO Endpoints (Sender Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/tariffs` | Fetch list of all tariffs (paginated, supports `date_from`/`date_to`) | ### eMSP Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | PUT | `/tariffs/{country_code}/{party_id}/{tariff_id}` | Push a full tariff object (create or replace) | | DELETE | `/tariffs/{country_code}/{party_id}/{tariff_id}` | Remove a tariff | ### Key Tariff Data Fields | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique tariff identifier | | `currency` | string | ISO 4217 currency code | | `elements` | TariffElement[] | List of pricing elements | | `type` | TariffType | AD_HOC_PAYMENT, PROFILE_CHEAP, PROFILE_FAST, PROFILE_GREEN, REGULAR (2.2.1 only) | | `tariff_alt_text` | DisplayText[] | Human-readable tariff description | | `tariff_alt_url` | URL | Link to a human-readable tariff page | | `energy_mix` | EnergyMix | Energy source information (renewable percentage, etc.) | | `last_updated` | DateTime | Timestamp of last update | ### Tariff Elements and Restrictions Each `TariffElement` contains a list of `PriceComponent` objects and optional `TariffRestrictions`: **Price Components**: | Field | Description | |-------|-------------| | `type` | ENERGY (per kWh), FLAT (per session), PARKING_TIME (per hour idle), TIME (per hour charging) | | `price` | Price per unit excluding VAT | | `step_size` | Minimum granularity (e.g., step_size=300 for TIME means billing in 5-minute increments) | **Tariff Restrictions** (conditions under which the element applies): | Field | Description | |-------|-------------| | `start_time` / `end_time` | Time-of-day restrictions | | `start_date` / `end_date` | Date range restrictions | | `min_kwh` / `max_kwh` | Energy consumption range | | `min_power` / `max_power` | Power range | | `min_duration` / `max_duration` | Session duration range | | `day_of_week` | Day-of-week restrictions | This structure enables complex pricing models: different rates for peak vs off-peak hours, penalties for overstaying after charging completes, tiered energy pricing, and more. ## How Does the Tokens Module Handle Authorization? The Tokens module handles driver authorization. eMSPs push their driver tokens (RFID cards, app credentials) to CPOs so that authorization can happen locally without requiring a real-time API call for every charge attempt. **Implemented by**: eMSP (sender/owner of token data), CPO (receiver) Note the reversed ownership: unlike most modules where the CPO is the data owner, here the eMSP owns and pushes token data to the CPO. ### eMSP Endpoints (Sender Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/tokens` | Fetch list of all tokens (paginated, supports `date_from`/`date_to`) | | GET | `/tokens/{token_uid}` | Fetch a specific token (2.1.1) | ### CPO Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/tokens/{country_code}/{party_id}/{token_uid}` | Fetch a specific token | | PUT | `/tokens/{country_code}/{party_id}/{token_uid}` | Push a full token (create or replace) | | PATCH | `/tokens/{country_code}/{party_id}/{token_uid}` | Partial update to a token | | POST | `/tokens/{token_uid}/authorize` | Real-time authorization request (CPO asks eMSP to authorize a token) | ### Key Token Data Fields | Field | Type | Description | |-------|------|-------------| | `uid` | string | Unique token identifier (e.g., RFID UID) | | `type` | TokenType | `RFID`, `OTHER` (2.1.1); `RFID`, `APP_USER`, `AD_HOC_USER`, `OTHER` (2.2.1) | | `auth_id` | string | Authorization identifier linking the token to a contract | | `visual_number` | string | Number printed on the token (if physical card) | | `issuer` | string | Name of the token issuer | | `valid` | boolean | Whether the token is currently valid for authorization | | `whitelist` | WhitelistType | `ALWAYS` (always accept offline), `ALLOWED` (accept offline, verify later), `ALLOWED_OFFLINE` (accept only when CPO is offline), `NEVER` (always verify online) — all four values present in 2.1.1 and 2.2.1 | | `language` | string | Preferred language of the driver | | `last_updated` | DateTime | Timestamp of last update | ### Real-Time Authorization The `POST /tokens/{token_uid}/authorize` endpoint is special. When a driver presents an RFID card at a charger, the CPO's backend can call this endpoint on the eMSP to get a real-time authorization decision. The eMSP responds with an `AuthorizationInfo` object containing `ALLOWED`, `BLOCKED`, `EXPIRED`, `NO_CREDIT`, or `NOT_ALLOWED`. This is used when the whitelist value is `NEVER` or when the token is not in the CPO's local cache. ## What Does the Commands Module Enable? The Commands module enables remote operations on charge points through the roaming chain. An eMSP can instruct a CPO to start a session, stop a session, reserve a charger, or unlock a connector -- all on behalf of the driver. **Implemented by**: CPO (receiver of commands), eMSP (sender of commands) ### CPO Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | POST | `/commands/START_SESSION` | Request the CPO to start a charging session | | POST | `/commands/STOP_SESSION` | Request the CPO to stop an active session | | POST | `/commands/RESERVE_NOW` | Request the CPO to reserve a charge point | | POST | `/commands/UNLOCK_CONNECTOR` | Request the CPO to unlock a connector | ### eMSP Endpoints (Callback) | Method | Path | Description | |--------|------|-------------| | POST | `{callback_url}` | Async result callback -- CPO posts the command result to the URL provided in the original request | ### Command Request Fields **START_SESSION**: | Field | Description | |-------|-------------| | `response_url` | Callback URL for the async result | | `token` | Token object identifying the driver | | `location_id` | Target location | | `evse_uid` | Target EVSE (optional in 2.1.1, required in 2.2.1) | **STOP_SESSION**: | Field | Description | |-------|-------------| | `response_url` | Callback URL for the async result | | `session_id` | ID of the session to stop | **RESERVE_NOW**: | Field | Description | |-------|-------------| | `response_url` | Callback URL for the async result | | `token` | Token object identifying the driver | | `location_id` | Target location | | `evse_uid` | Target EVSE | | `expiry_date` | When the reservation expires | **UNLOCK_CONNECTOR**: | Field | Description | |-------|-------------| | `response_url` | Callback URL for the async result | | `location_id` | Target location | | `evse_uid` | Target EVSE | | `connector_id` | Target connector | ### Asynchronous Command Flow Commands are asynchronous by design. The flow is: 1. eMSP sends `POST /commands/START_SESSION` to the CPO 2. CPO responds immediately with `ACCEPTED` or `REJECTED` (synchronous response indicating whether the command was received, not whether it succeeded) 3. CPO forwards the command to the charger via [OCPP](/blog/what-is-ocpp) 4. When the charger responds, the CPO sends the final result (`ACCEPTED`, `REJECTED`, `TIMEOUT`, `UNKNOWN_SESSION`, etc.) to the `response_url` provided in the original request This two-step flow is necessary because charger communication via OCPP can take several seconds. The eMSP must handle both the synchronous acknowledgment and the asynchronous callback. ## ChargingProfiles Module (2.2.1 Only) The ChargingProfiles module was introduced in OCPI 2.2.1 to enable smart charging through the roaming chain. It allows an eMSP or hub to set power limits on active charging sessions, enabling demand response, fleet management, and grid balancing use cases. **Implemented by**: CPO (receiver), eMSP (sender) ### CPO Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | PUT | `/chargingprofiles/{session_id}` | Set or update a charging profile for an active session | | DELETE | `/chargingprofiles/{session_id}` | Clear the charging profile for an active session | | GET | `/chargingprofiles/{session_id}` | Request the active charging profile for a session | ### eMSP Endpoints (Callback) | Method | Path | Description | |--------|------|-------------| | POST | `{callback_url}` | Async result callback with the command outcome or the active profile | ### Charging Profile Structure | Field | Type | Description | |-------|------|-------------| | `start_date_time` | DateTime | Start time for the profile | | `duration` | integer | Duration in seconds | | `charging_rate_unit` | ChargingRateUnit | W (watts) or A (amperes) | | `min_charging_rate` | number | Minimum charging rate | | `charging_profile_period` | ChargingProfilePeriod[] | Time-based power limits | Each `ChargingProfilePeriod` specifies: - `start_period`: Offset in seconds from `start_date_time` - `limit`: Maximum power (W) or current (A) for this period This module maps closely to [OCPP's Smart Charging profile](/blog/smart-charging-explained). The CPO translates the OCPI charging profile into an OCPP `SetChargingProfile` request sent to the charger. ## HubClientInfo Module (2.2.1 Only) The HubClientInfo module is used exclusively in hub-based topologies (like [GIREVE](/blog/gireve-hub-integration) or [Hubject](https://www.hubject.com/)). It allows the hub to inform connected parties about the status and capabilities of other parties connected to the hub. **Implemented by**: Hub (sender), CPO/eMSP (receiver) ### Hub Endpoints (Sender Interface) | Method | Path | Description | |--------|------|-------------| | GET | `/hubclientinfo` | Fetch list of all connected parties (paginated) | ### CPO/eMSP Endpoints (Receiver Interface) | Method | Path | Description | |--------|------|-------------| | PUT | `/hubclientinfo/{country_code}/{party_id}` | Push client info for a connected party | | DELETE | `/hubclientinfo/{country_code}/{party_id}` | Notify that a party has disconnected | ### Key HubClientInfo Data Fields | Field | Type | Description | |-------|------|-------------| | `party_id` | string (CiString3) | Three-character party identifier (e.g. `EXP`) | | `country_code` | string | ISO 3166-1 alpha-2 country code (e.g. `FR`, `DE`) in 2.2.1 | | `role` | Role | `CPO`, `EMSP`, `HUB`, `NSP`, `NAP`, `SCSP`, `OTHER` | | `status` | ConnectionStatus | CONNECTED, OFFLINE, PLANNED, SUSPENDED | | `last_updated` | DateTime | Timestamp of last update | This module is primarily used for discovery. An eMSP can use it to know which CPOs are reachable through the hub and what their connection status is. ## OCPI Data Types Reference Several data types are shared across multiple modules. Understanding these is essential for correct implementation. ### Common Enumerations | Type | Values | Used In | |------|--------|---------| | `Status` | AVAILABLE, BLOCKED, CHARGING, INOPERATIVE, OUTOFORDER, PLANNED, REMOVED | Locations (EVSE status) | | `ConnectorType` | CHADEMO, IEC_62196_T1 (Type 1), IEC_62196_T2 (Type 2), IEC_62196_T2_COMBO (CCS2), TESLA_S, DOMESTIC_A, etc. | Locations (Connector) | | `ConnectorFormat` | SOCKET, CABLE | Locations (Connector) | | `PowerType` | AC_1_PHASE, AC_3_PHASE, DC | Locations (Connector) | | `Capability` | CHARGING_PROFILE_CAPABLE, CREDIT_CARD_PAYABLE, REMOTE_START_STOP_CAPABLE, RESERVABLE, RFID_READER, UNLOCK_CAPABLE | Locations (EVSE) | | `TokenType` | `RFID`, `OTHER` (2.1.1); `RFID`, `APP_USER`, `AD_HOC_USER`, `OTHER` (2.2.1) | Tokens | | `AuthMethod` | AUTH_REQUEST, COMMAND, WHITELIST | CDRs | | `SessionStatus` | ACTIVE, COMPLETED, INVALID, PENDING | Sessions | | `CommandResponseType` | NOT_SUPPORTED, REJECTED, ACCEPTED, UNKNOWN_SESSION, TIMEOUT | Commands | ### CdrToken Object (OCPI 2.2.1 only) The `CdrToken` is a lightweight token reference embedded within CDRs and Sessions in **OCPI 2.2.1**. It was introduced to replace the bare `auth_id` string used in 2.1.1. | Field | Type | Description | |-------|------|-------------| | `uid` | string | Token UID | | `type` | TokenType | `RFID`, `APP_USER`, `AD_HOC_USER`, `OTHER` | | `contract_id` | string | Contract identifier (e.g., EMAID) | > **In OCPI 2.1.1**, Sessions and CDRs identify the authorization with a bare `auth_id` string and an `auth_method` enum, not a structured `cdr_token` object. The 2.1.1 Session/CDR objects also embed the full `Location` rather than referencing it by IDs. ### DisplayText Object Used throughout OCPI for multilingual text content: | Field | Type | Description | |-------|------|-------------| | `language` | string | ISO 639-1 language code | | `text` | string | The text content | ### GeoLocation Object | Field | Type | Description | |-------|------|-------------| | `latitude` | string | Latitude in decimal degrees (string type to preserve precision) | | `longitude` | string | Longitude in decimal degrees | Note that coordinates are strings, not floating-point numbers. This is intentional to avoid floating-point precision loss during serialization. ## How Does OCPI Handle Errors and Status Codes? Every OCPI response includes a `status_code` field. This is distinct from the HTTP status code. The OCPI status code provides protocol-level information about the request outcome. ### OCPI Status Code Ranges | Range | Category | Description | |-------|----------|-------------| | 1xxx | Success | Request processed successfully | | 2xxx | Client errors | Problem with the request from the client | | 3xxx | Server errors | Problem on the server side | | 4xxx | Hub errors (2.2.1 only) | Problem in hub-mediated routing; not present in 2.1.1 | ### Specific Status Codes | Code | Meaning | |------|---------| | 1000 | Generic success | | 2000 | Generic client error | | 2001 | Invalid or missing parameters | | 2002 | Not enough information (e.g., unknown location) | | 2003 | Unknown token | | 3000 | Generic server error | | 3001 | Unable to use the client's API (e.g., connection refused, timeout) | | 3002 | Unsupported version | | 3003 | No matching endpoints | ### HTTP Status Codes OCPI also uses standard HTTP status codes: | HTTP Code | Usage | |-----------|-------| | 200 | Successful GET, PUT, PATCH, DELETE | | 201 | Successful POST (resource created) | | 400 | Bad request (malformed JSON, missing required fields) | | 401 | Unauthorized (invalid or missing token) | | 404 | Resource not found | | 405 | Method not allowed | A critical implementation detail: always check both the HTTP status code AND the OCPI status code. A 200 HTTP response with an OCPI status code of 2001 means the request was received but contained invalid parameters. Many implementations incorrectly check only the HTTP code and miss protocol-level errors. ### Pagination All `GET` list endpoints support pagination through the following headers and parameters: **Request parameters**: `offset` (starting index), `limit` (max items per page), `date_from`, `date_to` **Response headers**: `X-Total-Count` (total number of objects), `X-Limit` (server-imposed max per page), `Link` (URL to next page) Always respect the server's `X-Limit` header. If you request `limit=1000` but the server returns `X-Limit: 100`, you must paginate with 100-item pages. ## What Changed Between OCPI 2.1.1 and 2.2.1? While the core architecture remains the same, OCPI 2.2.1 introduced several important changes. The full specifications for both versions are published by the [EV Roaming Foundation](https://evroaming.org/): ### New Modules in 2.2.1 - **ChargingProfiles**: Smart charging through the roaming chain (described above) - **HubClientInfo**: Hub connection status information (described above) ### Structural Changes | Area | 2.1.1 | 2.2.1 | |------|-------|-------| | **Token authorize** | `POST /tokens/{token_uid}/authorize` | Path includes `{type}`: `POST /tokens/{token_uid}/authorize?type=RFID` | | **CDR sender GET by ID** | `GET /cdrs/{cdr_id}` available | Removed from sender interface | | **Session sender GET by ID** | `GET /sessions/{session_id}` available | Removed from sender interface | | **Tariff types** | No `type` field | Added `TariffType` enum for categorization | | **Location time zones** | Not available | Added `time_zone` field to Location objects | | **EVSE ID format** | Recommended | More strictly defined | | **Connector ID in commands** | Not required for START_SESSION | `evse_uid` required for START_SESSION | ### Module Identifier Changes The module identifiers used in version endpoint discovery are the same across both versions: `credentials`, `locations`, `sessions`, `cdrs`, `tariffs`, `tokens`, `commands`. The 2.2.1 additions use `chargingprofiles` and `hubclientinfo`. ### Data Model Changes In 2.2.1, several objects gained additional fields for richer data exchange. The `Location` object added `time_zone` and `publish` fields. The `Tariff` object added the `type` field for categorizing pricing structures. The `Token` object refined the whitelist types and added `group_id` for corporate fleet management. If you are implementing a new system, target 2.2.1 as the primary version. Most hubs and major CPOs/eMSPs support 2.2.1. Maintain 2.1.1 compatibility only if your roaming partners require it. ## Frequently Asked Questions ### How does OCPI differ from OCPP? [OCPP](/blog/what-is-ocpp) is the protocol between a charger and a backend system (CPMS). It uses WebSocket connections and handles charge point management, firmware updates, and local authorization. OCPI is the protocol between backend systems (CPO-to-eMSP or CPO-to-Hub). It uses standard REST APIs and handles roaming, data exchange, and inter-network billing. A typical deployment uses both: OCPP from charger to CPO backend, and OCPI from CPO backend to eMSP or hub. ### Do I need to implement all OCPI modules? No. The only mandatory module is Credentials. All other modules are optional. In practice, a minimal viable implementation typically includes Locations, Sessions, CDRs, and Tokens. Commands is highly recommended if you want to support remote start/stop from roaming partners. Tariffs is important for cost transparency. ### How do roaming hubs like GIREVE fit into the endpoint structure? A [roaming hub](/blog/gireve-hub-integration) acts as an intermediary. Instead of establishing direct peer-to-peer OCPI connections with every partner, you connect once to the hub. The hub then proxies requests to and from all other connected parties. From an endpoint perspective, your implementation is identical -- you implement the same sender/receiver interfaces. The only addition is the HubClientInfo module (2.2.1), which the hub uses to inform you about other connected parties. ### What happens if a push update fails? OCPI does not define a retry mechanism in the specification. If a push request fails (network error, 5xx response), the sending party should implement its own retry logic with exponential backoff. The pull mechanism serves as a safety net: the receiving party's periodic pull synchronization will eventually catch updates that were missed during push failures. ### Can I use OCPI without a roaming hub? Yes. OCPI supports direct peer-to-peer connections between a CPO and an eMSP. This is common in markets where a CPO has a small number of roaming partners. However, as the number of partners grows, the hub model becomes more efficient because it reduces the number of connections from O(n^2) to O(n). ### What is the difference between PUT and PATCH in OCPI? `PUT` replaces the entire object. The request body must contain all required fields. `PATCH` performs a partial update -- only the fields included in the request body are updated. In practice, use `PUT` when creating or fully replacing an object, and `PATCH` for incremental updates like status changes. A `PATCH` with a field set to `null` removes that optional field from the object. --- OCPI's module-based, REST architecture makes it approachable for any team with HTTP API experience. The key to a successful implementation is getting the credential handshake right, implementing both push and pull modes for resilience, and testing thoroughly against real roaming partners or a hub's sandbox environment. For testing your [OCPP charger integration](/blog/what-is-ocpp) that feeds data into your OCPI layer, an [OCPP emulator](/) can validate your entire charging and roaming chain end-to-end. --- ## How to Implement OCPI Roaming: A Complete Guide Source: https://ocpplab.com/blog/how-to-implement-ocpi-roaming Implement OCPI 2.1.1 roaming for your EV charging network. A step-by-step guide to all 7 modules, credentials, hub integration, and testing for CPOs and eMSPs. **Quick answer:** To implement OCPI roaming, define your role (CPO, eMSP, or both), choose OCPI 2.1.1, and pick a roaming hub or direct P2P. Build version discovery and credential exchange first, then Locations, Tokens, Sessions, CDRs, and Tariffs, and connect through a hub like GIREVE or Hubject. Expect a basic build to take several weeks. Implementing OCPI roaming is one of the most impactful things you can do for your EV charging business. It connects your network to thousands of chargers (if you are an eMSP) or thousands of drivers (if you are a CPO). But the protocol documentation is dense, the edge cases are numerous, and the testing options are limited. This guide walks you through the full OCPI 2.1.1 implementation process, step by step. In our experience, a basic implementation takes a small team several weeks. A production-grade implementation with hub certification, robust error handling, and real-time sync takes considerably longer—on the order of several months, depending on your existing infrastructure. We are going to cover every module you need, in the order you should build them. ## Before You Start Before writing a single line of code, you need to make three decisions. ### 1. Define Your Role: CPO, eMSP, or Both Your role determines which OCPI modules you implement and in which direction data flows. - **CPO (Charge Point Operator)**: You own and operate chargers. You push location data, receive authorization requests, send session updates, and generate CDRs. - **eMSP (e-Mobility Service Provider)**: You manage drivers and their payments. You push tokens, receive session data, receive CDRs, and display tariffs. - **Both**: Many companies operate as both CPO and eMSP. You will need to implement both sides of every module. If you are unsure about the distinction, read our breakdown of [CPO vs eMSP roles](/blog/cpo-vs-emsp-explained) before continuing. ### 2. Choose Your OCPI Version OCPI 2.1.1 is the recommended starting point. It has the broadest adoption across European roaming hubs, is well-documented in the [official OCPI specification](https://github.com/ocpi/ocpi) maintained by the [EVRoaming Foundation](https://evroaming.org/ocpi/), and covers all core roaming use cases. OCPI 2.2 and 2.2.1 add features like smart charging commands and improved tariff structures, but hub support varies. Start with 2.1.1, then upgrade modules incrementally. ### 3. Select a Roaming Hub or Direct P2P You have two connectivity options: - **Hub-based roaming** (GIREVE, Hubject, e-clearing.net): One integration gives you access to hundreds of partners. The hub handles message routing and often provides certification testing. This is the standard approach. - **Direct peer-to-peer**: You connect directly to each partner. More control, but you need to manage each connection individually. Only practical if you have a small number of partners. For most companies, hub-based roaming through [GIREVE](/blog/gireve-hub-integration) or Hubject is the right call. The rest of this guide assumes hub-based integration, though the module implementation is identical for P2P. ## Step 1: How Do You Implement Version Discovery? Every OCPI implementation starts with the `/versions` endpoint. This is the entry point that tells partners which OCPI versions you support and where to find each module. Your `/versions` endpoint returns a list of supported versions: ```json { "status_code": 1000, "data": [ { "version": "2.1.1", "url": "https://your-platform.com/ocpi/2.1.1" } ] } ``` When a partner hits the version-specific URL, they get the list of module endpoints: ```json { "status_code": 1000, "data": { "version": "2.1.1", "endpoints": [ { "identifier": "credentials", "url": "https://your-platform.com/ocpi/2.1.1/credentials" }, { "identifier": "locations", "url": "https://your-platform.com/ocpi/2.1.1/locations" }, { "identifier": "tokens", "url": "https://your-platform.com/ocpi/2.1.1/tokens" }, { "identifier": "sessions", "url": "https://your-platform.com/ocpi/2.1.1/sessions" }, { "identifier": "cdrs", "url": "https://your-platform.com/ocpi/2.1.1/cdrs" }, { "identifier": "tariffs", "url": "https://your-platform.com/ocpi/2.1.1/tariffs" } ] } } ``` Implementation notes: - Use HTTPS. No exceptions. - All responses follow the same envelope: `status_code`, `data`, `timestamp`, and optionally `status_message`. - The `status_code` 1000 means success. Anything in the 2xxx or 3xxx range indicates an error. This endpoint is trivial to build, but get it right. Every partner interaction begins here. ## Step 2: How Does Credential Exchange Work? The credential exchange is the OCPI handshake. It establishes mutual trust between two parties by exchanging authentication tokens. Here is the flow: 1. **Party A** receives an initial token (TOKEN_A) out-of-band, typically through a hub portal or direct email. 2. **Party A** uses TOKEN_A to call Party B's `/versions` endpoint, discovering the credentials module URL. 3. **Party A** sends a `POST /credentials` request to Party B, including Party A's own credentials (its URL and a new token for Party B to use). 4. **Party B** validates TOKEN_A, stores Party A's credentials, and responds with Party B's credentials (including TOKEN_B). 5. **From this point forward**, Party A uses TOKEN_B to authenticate requests to Party B, and Party B uses the token Party A provided to authenticate requests to Party A. The POST body looks like this (OCPI 2.1.1 — note `country_code` is the alpha-3 ISO 3166-1 code; OCPI 2.2.1 uses alpha-2): ```json { "url": "https://party-a.com/ocpi/versions", "token": "party-a-token-for-party-b-to-use", "party_id": "PAR", "country_code": "FRA", "business_details": { "name": "Party A" } } ``` Critical implementation details: - **Store both tokens securely.** These are bearer tokens used for all subsequent API calls. - **TOKEN_A is single-use.** After the credential exchange completes, TOKEN_A should be invalidated. Only the newly exchanged tokens are valid. - **Support `PUT /credentials`** for token rotation. Partners will periodically update their tokens, and your system must handle this without downtime. - **Validate the token on every request.** Check the Authorization header against your stored tokens. Return a 401 if the token does not match. If you are integrating through a hub like GIREVE, the hub manages the initial token distribution and may handle parts of the credential exchange on your behalf. But you still need to implement the credentials module. ## Step 3: How Do You Implement the Locations Module (CPO)? If you are a CPO, the Locations module is your most important implementation. It publishes your charger infrastructure to the roaming network. OCPI models charging infrastructure as a three-level hierarchy: - **Location**: A physical site (e.g., a parking garage, a highway rest stop). Contains address, coordinates, opening hours, and facilities. - **EVSE**: An Electric Vehicle Supply Equipment unit at that location. Each EVSE has a unique `evse_uid` and a status (`AVAILABLE`, `BLOCKED`, `CHARGING`, `INOPERATIVE`, `OUTOFORDER`, `PLANNED`, `REMOVED`, `RESERVED`, `UNKNOWN`). - **Connector**: A physical plug on an EVSE. Defined by connector type (Type 2, CCS, CHAdeMO), power type (AC/DC), and max power. A typical location object: ```json { "id": "LOC001", "type": "ON_STREET", "name": "Main Street Charging Hub", "address": "123 Main Street", "city": "Paris", "country": "FRA", "coordinates": { "latitude": "48.8566", "longitude": "2.3522" }, "evses": [ { "uid": "EVSE001", "status": "AVAILABLE", "connectors": [ { "id": "1", "standard": "IEC_62196_T2", "format": "SOCKET", "power_type": "AC_3_PHASE", "max_voltage": 400, "max_amperage": 32 } ] } ], "last_updated": "2025-03-16T10:30:00Z" } ``` You need to support two data flow patterns: - **Pull (GET)**: Partners can fetch your full location list via pagination. Implement `GET /locations` with `offset` and `limit` query parameters, and support `date_from`/`date_to` filtering so partners can pull only recent changes. - **Push (PUT/PATCH)**: For real-time updates, push changes to connected partners or the hub. When an EVSE status changes from AVAILABLE to CHARGING, send a `PATCH` to the partner's receiver endpoint immediately. Real-time status updates are critical. Drivers rely on up-to-date availability information. If your status updates lag by more than a few seconds, the user experience degrades rapidly, with drivers arriving at chargers that show as available but are actually in use. ## Step 4: How Do You Implement the Tokens Module (eMSP)? If you are an eMSP, the Tokens module lets CPOs authorize your drivers at their chargers. A token represents a driver's authorization credential, typically linked to an RFID card, an app account, or both. You push your tokens to connected CPOs so they can perform local authorization without calling back to your server for every charge session. A token object: ```json { "uid": "RFID-001234567890", "type": "RFID", "auth_id": "USER-12345", "issuer": "Your eMSP Name", "valid": true, "whitelist": "ALLOWED", "last_updated": "2025-03-16T08:00:00Z" } ``` The `whitelist` field controls authorization behavior. OCPI defines four values: - **ALWAYS**: The CPO must always authorize locally without contacting the eMSP. - **ALLOWED**: Local authorization is allowed, and the CPO may also call the eMSP for real-time verification when it wants to. - **ALLOWED_OFFLINE**: Local authorization is allowed only when the CPO cannot reach the eMSP (offline fallback). - **NEVER**: The CPO must always do a real-time authorization request to the eMSP — never authorize locally. (Note: to reject a token entirely, set the token's `valid` flag to `false` rather than using a `whitelist` value — there is no `NOT_ALLOWED` value in `WhitelistType`.) For real-time authorization (when `whitelist` is `NEVER` or when the CPO wants to double-check), the CPO sends a `POST /tokens/{token_uid}/authorize` request to the eMSP. Your eMSP must respond within a few seconds. Slow responses mean drivers waiting at chargers, which is unacceptable. Push token updates to CPOs whenever a token is created, modified, or revoked. A driver losing their RFID card should result in an immediate token invalidation pushed to all connected CPOs. ## Step 5: How Do You Implement the Sessions Module? The Sessions module tracks active charging sessions in real time. CPOs push session data to eMSPs so drivers can see their ongoing charge in their app. A session goes through these states: 1. **ACTIVE**: Charging is in progress. The CPO sends periodic updates with current energy delivered and cost. 2. **COMPLETED**: Charging finished. Final session data is sent. 3. **INVALID**: Something went wrong. The session is flagged for review. The CPO creates a session when charging starts and pushes updates to the eMSP via `PUT /sessions/{session_id}`. Updates should be sent frequently; the more often you push, the better the driver experience, at the cost of more traffic. Match your cadence to what your hub partner expects. A session object includes: ```json { "id": "SESSION-001", "start_datetime": "2025-03-16T10:00:00Z", "kwh": 15.5, "auth_id": "USER-12345", "location": { "...location reference..." }, "currency": "EUR", "total_cost": 8.25, "status": "ACTIVE", "last_updated": "2025-03-16T10:30:00Z" } ``` Key implementation points: - **Idempotency**: Use `PUT` semantics. If the eMSP receives the same session update twice, it should overwrite, not duplicate. - **Cost calculation**: The CPO calculates the running cost based on published tariffs. The eMSP displays this to the driver. - **Session references**: Link sessions to locations, EVSEs, and connectors so the eMSP can show context to the driver. ## Step 6: How Do You Implement the CDRs Module? Charge Detail Records (CDRs) are the billing backbone of OCPI roaming. After a session completes, the CPO generates a CDR and pushes it to the eMSP. A CDR is the final, immutable record of a charging session. It contains everything needed for settlement: ```json { "id": "CDR-001", "start_date_time": "2025-03-16T10:00:00Z", "stop_date_time": "2025-03-16T10:45:00Z", "auth_id": "USER-12345", "total_energy": 22.5, "total_time": 2700, "total_cost": 12.75, "currency": "EUR", "charging_periods": [ { "start_date_time": "2025-03-16T10:00:00Z", "dimensions": [ { "type": "ENERGY", "volume": 22.5 }, { "type": "TIME", "volume": 0.75 } ] } ], "last_updated": "2025-03-16T10:46:00Z" } ``` The CDR lifecycle: 1. CPO generates the CDR after the session ends. 2. CPO pushes the CDR to the eMSP via `POST /cdrs`. 3. The eMSP validates the CDR against the session data and published tariffs. 4. If accepted, the eMSP processes the charge to the driver and settles with the CPO according to their roaming agreement. CDRs are critical for revenue. Every field matters. Missing or incorrect data leads to billing disputes, which are expensive to resolve manually. Validate your CDR generation against multiple tariff scenarios before going live. ## Step 7: How Do You Implement the Tariffs Module? The Tariffs module lets CPOs publish their pricing so eMSPs can display costs to drivers before they start charging. OCPI tariffs support multiple price components: - **ENERGY**: Price per kWh of energy delivered. - **TIME**: Price per hour of charging time. - **FLAT**: A fixed fee per session. - **PARKING_TIME**: Price per hour after charging completes (to discourage blocking chargers). A tariff example: ```json { "id": "TARIFF-001", "currency": "EUR", "elements": [ { "price_components": [ { "type": "FLAT", "price": 1.00, "step_size": 1 }, { "type": "ENERGY", "price": 0.35, "step_size": 1 }, { "type": "PARKING_TIME", "price": 5.00, "step_size": 300 } ] } ], "last_updated": "2025-03-16T08:00:00Z" } ``` The `step_size` field defines billing granularity. A `step_size` of 1 for energy means billing per Wh. A `step_size` of 300 for parking time means billing in 5-minute blocks. Getting step_size wrong is one of the most common tariff bugs, so test your cost calculations thoroughly. Tariffs can include restrictions (time of day, min/max kWh, specific connector types) that determine when each tariff element applies. This complexity is where most implementations struggle. Start simple, with a flat energy tariff, then add complexity. ## Step 8: Hub Integration With your modules implemented, it is time to connect to a roaming hub. ### GIREVE [GIREVE](/blog/gireve-hub-integration) is the dominant European roaming hub for OCPI. Their integration process: 1. **Sign a roaming agreement** with GIREVE. 2. **Connect to their test environment** (IOP QA). Implement version discovery and credential exchange against their test endpoints. 3. **Pass certification tests.** GIREVE runs automated tests against each module. They test standard flows, edge cases, and error handling. 4. **Go live on production.** Once certified, GIREVE connects you to their partner network. GIREVE has specific requirements beyond the OCPI spec, such as mandatory fields, data quality checks, and response time limits. Read [GIREVE's integration documentation](https://www.gireve.com/) carefully. ### Hubject Hubject primarily uses [OICP](https://github.com/hubject/oicp) (their own protocol), but increasingly supports OCPI as well. If you are evaluating both, see our [comparison of OCPI vs OICP vs OCHP](/blog/ocpi-vs-oicp-vs-ochp). ### Hub-Specific Considerations - **Message routing**: Hubs add a routing layer. Your `country_code` and `party_id` are used to route messages to the right partner. - **Data quality**: Hubs enforce data quality standards. Incomplete location data or missing GPS coordinates will be rejected. - **Response times**: Hubs typically require responses within a short, defined window, so optimize your endpoints and check your hub's documented limits. - **Pagination**: Hubs pull large datasets. Your pagination implementation must handle thousands of records efficiently. ## How Do You Test Your OCPI Implementation? This is where most teams struggle. Testing OCPI properly requires a counterpart, a CPO to test your eMSP code and an eMSP to test your CPO code. Your testing options: - **Test against the hub's QA environment.** This is necessary but limited. Hub test environments often have restricted scenarios and slow feedback cycles. - **Test against a real partner.** Slow, requires coordination, and you risk exposing bugs in a semi-production setting. - **Build your own mock server.** Time-consuming to build and maintain. You end up spending as much time on the mock as on the real implementation. - **Use OCPPLab.** Our platform simulates both CPO and eMSP endpoints, letting you test every module and every edge case without waiting for a partner or hub. You can run through the full credential exchange, push locations, authorize tokens, create sessions, and generate CDRs, all against a simulated counterpart that validates your implementation against the OCPI spec. A solid testing strategy covers: - **Happy path**: Full flow from credential exchange through CDR generation. - **Error handling**: Invalid tokens, malformed requests, timeout scenarios. - **Edge cases**: Timezone boundaries in CDRs, tariff changes mid-session, concurrent session updates. - **Performance**: Pagination with thousands of locations, high-frequency status updates. ## What Are the Most Common OCPI Implementation Pitfalls? After working with dozens of OCPI implementations, these are the issues we see most frequently. **Timezone handling in CDRs.** OCPI requires UTC timestamps. But charger hardware often reports local time. If your conversion is wrong, CDR costs will be calculated against the wrong tariff period. Always store and transmit in UTC. Convert to local time only at the display layer. **Tariff calculation mismatches.** The CPO calculates costs. The eMSP verifies costs. If their tariff interpretations differ (usually because of `step_size` rounding), every CDR triggers a billing dispute. Test tariff calculations with the same test cases on both sides. **Stale location data.** If your EVSE status updates fail silently, drivers see outdated availability. Implement monitoring on your push mechanism. Alert when updates fail or when an EVSE has not reported a status change in an unusually long time. **Token caching gone wrong.** CPOs cache eMSP tokens for offline authorization. If your cache invalidation is broken, revoked tokens still authorize sessions. Implement cache TTLs and honor real-time token updates from eMSPs. **Pagination off-by-one errors.** OCPI pagination uses `offset` and `limit`. Off-by-one errors cause partners to miss records or fetch duplicates. Test with datasets of exactly `limit` size, `limit + 1`, and `limit - 1`. **Ignoring the `last_updated` field.** Every OCPI object has a `last_updated` timestamp. Partners use this for incremental sync. If you do not update this field when data changes, partners will miss updates. Make sure every data mutation updates `last_updated`. ## FAQ ### How long does a full OCPI implementation take? A basic implementation covering version discovery, credentials, locations, and sessions takes a small backend team several weeks. Adding CDRs, tariffs, token real-time authorization, and hub certification extends this to several months. The protocol itself is not complex, but edge cases, testing, and hub certification add significant time. ### Can I implement OCPI without connecting to a hub? Yes. OCPI supports direct peer-to-peer connections. You exchange credentials directly with each partner. This works if you have a small number of partners, but does not scale. Most companies start with hub integration. ### Which OCPI modules are mandatory? For OCPI 2.1.1, only the Credentials module is technically mandatory. But for practical roaming, you need Locations (CPO), Tokens (eMSP), Sessions, and CDRs at minimum. Tariffs are strongly recommended so eMSPs can display pricing to drivers. ### How does OCPI relate to OCPP? [OCPP](/blog/what-is-ocpp) is the protocol between a charger and its management system (CPO backend). [OCPI](/blog/what-is-ocpi) is the protocol between CPO backends and eMSP backends for roaming. They solve different problems but work together: OCPP gets data from the charger to the CPO, and OCPI shares that data with roaming partners. ### Do I need to support both pull and push for every module? In practice, yes. Pull (GET with pagination) is used for initial data sync and recovery. Push (PUT/PATCH/POST) is used for real-time updates. Hubs typically rely on pull for bulk data and push for real-time changes. Implement both from the start. ### What authentication does OCPI use? OCPI uses token-based authentication via the `Authorization` header with a `Token` prefix (e.g., `Authorization: Token abc123`). Tokens are exchanged during the credential handshake and can be rotated via `PUT /credentials`. There is no OAuth, no API keys, just bearer tokens exchanged through the protocol itself. ## Next Steps If you are starting your OCPI implementation, begin with version discovery and credential exchange. Get those working against a test counterpart before moving to the data modules. Build Locations or Tokens next (depending on your role), then Sessions, CDRs, and Tariffs. For a deeper understanding of the protocol itself, read our [introduction to OCPI](/blog/what-is-ocpi). If you are evaluating which roaming protocol to adopt, our [comparison of OCPI, OICP, and OCHP](/blog/ocpi-vs-oicp-vs-ochp) covers the tradeoffs. And when you are ready to test, use [OCPPLab](/) to validate your implementation against simulated CPO and eMSP endpoints before going live with real partners. --- ## Best OCPP Testing Tools in 2026: Compared & Explained Source: https://ocpplab.com/blog/best-ocpp-testing-tools-compared Compare 5 of the best OCPP testing tools in 2026 — OCPPLab, SteVe, OCPP.js, EVerest, and MobileCharger — across scale, automation, and pricing tradeoffs. **Quick answer:** The best OCPP testing tools in 2026 are OCPPLab, SteVe, OCPP.js, EVerest, and MobileCharger Simulator. OCPPLab is a cloud platform for simulating charge points at scale; SteVe and EVerest are open-source, OCPP.js a Node.js library, and MobileCharger Simulator a mobile app for field technicians. The right pick depends on scale, automation, and integration needs. The best OCPP testing tools in 2026 are **OCPPLab** (cloud-based simulator and emulator platform), **SteVe** (open-source CPMS), **OCPP.js** (Node.js library), **EVerest** (Linux Foundation charging stack), and **MobileCharger Simulator** (mobile testing app). The right choice depends on whether you need a full cloud platform for CPMS validation at scale, an open-source library for custom protocol development, or a lightweight utility for field diagnostics. This guide provides a fair, detailed comparison across the criteria that matter for OCPP development and QA: protocol coverage, scalability, automation capabilities, pricing, and ease of integration. If you are building or testing a [CPMS](/blog/what-is-csms), charge point firmware, or charging network integration, this is the comparison you need. If you already know you need production-style validation, jump to [CPMS testing](/use-cases/csms-testing), [OCPP load testing](/use-cases/ocpp-load-testing), or [see pricing](/pricing). ## Quick Comparison Table | Feature | OCPPLab | SteVe | OCPP.js | EVerest | MobileCharger Simulator | |---|---|---|---|---|---| | **Type** | Cloud platform | Open-source CPMS | Node.js library | Open-source stack | Mobile app | | **OCPP 1.6** | Yes | Yes | Yes | Yes | Yes | | **OCPP 2.0.1** | Yes | Partial | Yes | Yes | No | | **OCPI Support** | Yes (2.1.1) | No | No | No | No | | **Cloud-hosted** | Yes | No (self-hosted) | N/A (library) | No (self-hosted) | N/A (mobile) | | **Max Charge Points** | 10,000+ | Depends on host | Depends on implementation | Depends on host | 1 | | **AI Test Automation** | Yes | No | No | No | No | | **Load Testing** | Yes | No | Manual only | No | No | | **CI/CD Integration** | Yes (API) | No | Yes (programmatic) | Partial | No | | **Pricing** | $99-499/mo + Enterprise | Free | Free | Free | Free (limited) / Paid | | **Support** | Dedicated + Slack | Community | Community | Community + LF members | Email | | **Setup Time** | Minutes | Hours-days | Hours (dev required) | Days-weeks | Minutes | | **Best For** | Scale testing, QA teams | Basic CPMS testing | Custom emulators | Firmware-level testing | Field technicians | ## Why Choose OCPPLab for Scale Testing? [OCPPLab](https://ocpplab.com) is a cloud-based OCPP testing platform purpose-built for simulating and emulating charge points at scale. It operates as a fully managed service, meaning there is nothing to install, configure, or host. You connect your CPMS to OCPPLab's cloud endpoints and immediately begin testing against simulated charge points. ### What OCPPLab Does Well **Scale testing** is OCPPLab's defining capability. The platform can simulate over 10,000 concurrent charge points connected to your CPMS, each generating realistic [OCPP WebSocket](/blog/ocpp-websocket-guide) traffic including BootNotification, Heartbeat, MeterValues, StatusNotification, and full transaction flows. This is essential for teams that need to validate their CPMS under production-like load before deployment. **Protocol coverage** spans OCPP 1.6 and OCPP 2.0.1, plus [OCPI 2.1.1](/blog/what-is-ocpi) for roaming integration testing. Having all three protocols in a single platform eliminates the need to maintain separate testing environments for each. **Workflow-based test automation** helps teams turn common protocol scenarios into repeatable regression checks. This includes smart charging profile validation, connector status cycling, and transaction interruption scenarios. **CI/CD integration** through OCPPLab's API means you can embed OCPP compliance and performance tests directly into your deployment pipeline. Every build gets validated against realistic charge point behavior before it reaches production. ### Limitations OCPPLab is a paid service. The $99/month starter tier is accessible for small teams, but the cost scales with usage, and enterprise features like custom OCPI hub simulation and dedicated load testing infrastructure require higher tiers. Teams with zero budget will find the free tools listed below more appropriate for basic testing, though they will need to accept the tradeoffs in scale and automation. OCPPLab simulates charge points, not the physical hardware. If you need to test firmware-level behavior, electrical signaling, or ISO 15118 Plug & Charge at the hardware layer, you need either physical chargers or a tool like EVerest. ### Best For Development teams and QA organizations building or operating a CPMS at scale. Particularly valuable for teams that need to validate performance under load, automate regression testing in CI/CD, or test OCPI roaming flows alongside [OCPP](/blog/what-is-ocpp). ## Is SteVe Right for CPMS Development? [SteVe](https://github.com/steve-community/steve) is an open-source CPMS written in Java. It implements the Central System side of the OCPP protocol, meaning it receives connections from charge points (real or simulated) rather than simulating charge points itself. SteVe has been a staple of the OCPP ecosystem for years and remains one of the most widely referenced open-source CPMS implementations. ### What SteVe Does Well **Zero cost and full source access.** SteVe is free under the GPL license. You can fork it, modify it, and host it on your own infrastructure without licensing fees. For startups and research teams, this is a significant advantage. **Solid OCPP 1.6 support.** SteVe's implementation of OCPP 1.6 is mature and well-tested. It handles core operations like RemoteStartTransaction, RemoteStopTransaction, ChangeConfiguration, and GetDiagnostics reliably. The web dashboard provides a functional, if basic, management interface. **Community knowledge base.** SteVe has been around long enough that Stack Overflow, GitHub issues, and EV charging forums contain substantial troubleshooting information. If you hit a problem, someone has likely encountered it before. ### Limitations SteVe is a CPMS, not a charge point emulator. It does not generate simulated charge point connections to test another CPMS. You use SteVe to test charge points (or charge point emulators) against a CPMS, not the other way around. This is a fundamental architectural distinction that matters for your testing strategy. **OCPP 2.0.1 support is partial.** While there has been progress, SteVe's 2.0.1 implementation does not yet cover the full message set. Teams building exclusively for 2.0.1 should verify that the specific messages and features they need are supported before committing. **No OCPI support.** SteVe does not implement OCPI, so you cannot test roaming scenarios. If your roadmap includes integration with Hubject, [Gireve](/blog/gireve-hub-integration), or other roaming hubs, you will need a separate solution. **No load testing capabilities.** SteVe is a single-instance application. There is no built-in mechanism for simulating thousands of concurrent charge point connections or measuring CPMS performance under stress. **Setup and maintenance overhead.** SteVe requires a Java runtime, a MySQL/MariaDB database, and manual configuration. Keeping it updated, secured, and running reliably is your responsibility. ### Best For Teams that need a free, open-source CPMS for development and basic functional testing of charge points or charge point emulators. Particularly useful for learning the OCPP protocol, university research, and early-stage prototyping where budget is the primary constraint. ## When Should You Use OCPP.js? [OCPP.js](https://github.com/mikuso/ocpp-rpc) (and similar Node.js OCPP libraries) provides programmatic building blocks for creating OCPP clients and servers in JavaScript. It is not a ready-to-use testing platform but rather a library you use to build one. ### What OCPP.js Does Well **Developer flexibility.** OCPP.js gives you direct control over every OCPP message. You can construct arbitrary message sequences, inject malformed payloads, test edge cases, and build highly customized test harnesses tailored to your specific CPMS implementation. For developers who want to write code rather than click through a UI, this is the most natural approach. **OCPP 1.6 and 2.0.1 coverage.** The library supports both major protocol versions, and because you are writing code against the protocol directly, you can implement any message or extension you need. **CI/CD native.** Since your tests are JavaScript code, they integrate naturally into Node.js CI/CD pipelines. You can run OCPP test suites as part of your standard test framework using Mocha, Jest, or any other runner. **Free and open-source.** Licensed under MIT, OCPP.js is free for any use including commercial. No licensing restrictions, no usage limits. ### Limitations **Development effort required.** OCPP.js is a library, not a platform. Creating a useful test suite requires writing substantial code: connection management, message sequencing, state machines, result validation, and reporting. Teams without strong JavaScript developers will find this approach slow. **No built-in load testing.** You can spawn multiple WebSocket connections programmatically, but building a reliable load testing framework that generates thousands of concurrent realistic charge point sessions is a significant engineering project in itself. The library provides the protocol layer, not the orchestration. **No UI or dashboards.** There is no visual interface for monitoring tests, viewing results, or managing scenarios. Everything happens in code and terminal output. **No OCPI support.** Like SteVe, OCPP.js focuses exclusively on the OCPP protocol. Testing OCPI roaming flows requires separate tooling. **Maintenance burden.** As the OCPP specification evolves, you are responsible for updating your test code to match. Schema changes, new messages, and security requirements all require manual implementation effort. ### Best For Development teams with strong JavaScript expertise who need to build custom OCPP test harnesses, particularly for testing specific edge cases, protocol compliance, or non-standard behaviors that a general-purpose platform might not cover. ## What Makes EVerest Stand Out? [EVerest](https://github.com/EVerest) is a Linux Foundation Energy project that provides a complete open-source software stack for EV charging stations. It covers far more than OCPP testing, encompassing ISO 15118 communication, energy management, authentication, and charging station firmware. ### What EVerest Does Well **Full-stack charging station software.** EVerest is the most comprehensive open-source charging station implementation available. It handles everything from the low-level hardware abstraction (SLAC, HLC) to the high-level OCPP communication with a CPMS. If you need to understand or test the entire charging station software stack, EVerest is unmatched. **Strong OCPP 2.0.1 implementation.** EVerest's OCPP 2.0.1 module is actively maintained by Pionix and other contributors. It covers device management, smart charging, security profiles, and the full transaction model. This is one of the most complete open-source OCPP 2.0.1 implementations available. **ISO 15118 and Plug & Charge.** EVerest supports [ISO 15118 Plug & Charge](/blog/iso-15118-plug-and-charge) communication, including the TLS-based high-level communication protocol. If your testing requirements include ISO 15118, EVerest is one of very few options that provide this at the software level. **Linux Foundation backing.** EVerest benefits from corporate sponsors, a structured governance model, and regular release cadences. This is not a weekend side project; it is a professionally maintained ecosystem with long-term viability. ### Limitations **Complex setup.** EVerest is designed to run on Linux and requires a specific build environment (CMake, C++17, various system dependencies). Getting it running on a development machine takes hours to days depending on your familiarity with the toolchain. This is not a "download and run" tool. **Not a testing platform.** EVerest is charging station software, not a testing service. Using it for OCPP testing means configuring it as a simulated charging station and connecting it to your CPMS. This works, but it is repurposing a production firmware stack as a test tool, which introduces complexity that dedicated testing tools avoid. **Single charge point per instance.** Each EVerest instance simulates one charging station (potentially with multiple connectors). Simulating hundreds or thousands of charge points requires running hundreds or thousands of EVerest instances, which is operationally complex. **No OCPI support.** EVerest operates at the charge point level. OCPI is a backend-to-backend protocol between a CPO and eMSP, which is outside EVerest's scope. **Steep learning curve.** The documentation has improved significantly, but EVerest's modular architecture and C++ codebase present a learning curve for teams not experienced with embedded systems or Linux-based development. ### Best For Teams building or testing charging station firmware that need a reference implementation of the complete charging stack. Particularly valuable for hardware manufacturers, ISO 15118 integration testing, and organizations contributing to the open-source EV charging ecosystem. ## What Can MobileCharger Simulator Do? MobileCharger Simulator is a mobile application (available on Android and iOS) that turns a smartphone or tablet into a basic OCPP charge point emulator. It connects to a CPMS over WebSocket and can send core OCPP messages. ### What MobileCharger Simulator Does Well **Instant setup.** Install the app, enter your CPMS WebSocket URL, and start sending OCPP messages. There is no server to provision, no code to write, and no build environment to configure. For quick smoke tests, this is the fastest path to a working charge point simulation. **Field-friendly.** A mobile app is the most practical OCPP testing tool for field technicians commissioning chargers on-site. You can verify that a CPMS endpoint is reachable, test basic transaction flows, and confirm configuration without a laptop. **Core OCPP 1.6 operations.** The app covers the essential OCPP 1.6 messages: BootNotification, Heartbeat, Authorize, StartTransaction, StopTransaction, and StatusNotification. For basic functional verification, this covers the critical path. ### Limitations **Single charge point only.** The app simulates one charge point at a time. There is no mechanism for load testing, concurrent connections, or multi-station scenarios. **No OCPP 2.0.1.** As of early 2026, MobileCharger Simulator supports OCPP 1.6 only. Teams working with 2.0.1 need a different tool. **No automation.** Every test is manual. There is no scripting, no test sequences, no CI/CD integration. This is a point-and-click tool for one-off testing. **Limited message coverage.** Advanced OCPP features like smart charging profiles, firmware updates, local authorization list management, and security extensions are either absent or minimally supported. **No OCPI support.** Like most tools in this comparison, OCPI roaming testing is not in scope. ### Best For Field technicians and operations teams who need a quick, portable tool for verifying CPMS connectivity and basic OCPP transaction flows during charger commissioning or troubleshooting. ## How Do You Choose the Right OCPP Testing Tool? The right tool depends on what you are testing, at what scale, and with what resources. Here is a decision framework: **If you need cloud-based scale testing and QA automation**, choose **OCPPLab**. It provides managed infrastructure for simulating thousands of charge points, reusable workflow automation, and API-based CI/CD integration. The cost is justified if your CPMS needs to handle production-scale traffic. **If you need a free, open-source CPMS for development**, choose **SteVe**. It provides a functional CPMS that your charge point emulators or physical chargers can connect to. The zero cost makes it ideal for learning, prototyping, and early-stage development where budget is the binding constraint. **If you are building a custom charge point emulator or test harness**, choose **OCPP.js**. The programmatic control it offers is unmatched for teams that need to test specific protocol edge cases, build domain-specific test suites, or integrate OCPP testing into existing JavaScript toolchains. **If you need firmware-level or ISO 15118 testing**, choose **EVerest**. No other open-source project provides comparable depth across the full charging station software stack, from hardware abstraction to OCPP communication to Plug & Charge. **If you need a portable tool for field commissioning**, choose **MobileCharger Simulator**. Nothing else in this comparison is as fast to set up or as practical for on-site smoke tests by non-developers. **If you need comprehensive coverage**, consider combining tools. A common pattern is OCPPLab for scale and regression testing in CI/CD, with OCPP.js or EVerest for custom edge-case testing during development, and MobileCharger for field validation. These tools complement each other more than they compete. ## What Should You Look for in an OCPP Testing Tool? When evaluating any OCPP testing tool beyond the five covered here, use this checklist: - **OCPP version support.** Does it support both 1.6 and 2.0.1? Can it handle the specific messages and features your implementation uses? - **Scalability.** Can it simulate enough concurrent charge points to replicate your production environment? A tool that works for 10 chargers may collapse at 1,000. - **Protocol compliance.** Does it follow the OCPP specification strictly, or does it take shortcuts that mask bugs in your own implementation? - **Automation and CI/CD.** Can you run tests automatically on every commit, or does every test require manual intervention? - **OCPI and roaming.** If your roadmap includes roaming, does the tool support OCPI alongside OCPP? - **Realistic traffic patterns.** Does the tool generate realistic charge point behavior (concurrent sessions, intermittent connectivity, varied MeterValues), or does it send idealized traffic that does not match production reality? - **Error injection.** Can you simulate failures, malformed messages, network interruptions, and timeout scenarios? [Testing the unhappy paths](/blog/ocpp-testing-guide) is where most CPMS bugs hide. - **Reporting and observability.** Does the tool provide clear test results, message logs, and performance metrics? A test you cannot interpret is a test you cannot act on. - **Security testing.** Does it support OCPP security profiles, TLS, and certificate management? Security is not optional for production charging networks. - **Support and documentation.** When you hit a problem, can you get help? Community forums, documentation quality, and vendor support responsiveness all matter. ## Frequently Asked Questions ### Is there a free OCPP emulator? Yes. SteVe is a free open-source CPMS you can use to test charge points. OCPP.js is a free library for building custom charge point emulators. EVerest is a free, full-stack charging station software package. MobileCharger Simulator has a free tier for basic testing. OCPPLab is the only paid option in this comparison, though it offers trial access for evaluation. ### What is the best OCPP 2.0.1 testing tool? For comprehensive OCPP 2.0.1 testing at scale, OCPPLab provides the broadest message coverage with managed infrastructure. For open-source 2.0.1 development, EVerest has one of the most complete implementations. OCPP.js supports 2.0.1 programmatically but requires you to build the test infrastructure. SteVe has partial 2.0.1 support, and MobileCharger Simulator does not support 2.0.1. ### Can I use these tools for OCPP compliance certification? None of these tools replace formal [OCPP compliance certification from the Open Charge Alliance](https://openchargealliance.org/certification-program/). However, they can help you identify and fix compliance issues before submitting for certification. OCPPLab's protocol validation is the closest to a pre-certification check, while OCPP.js allows you to build test suites that mirror certification test cases. ### How many charge points do I need to simulate for load testing? This depends on your production target. A sensible guideline is to test comfortably above your expected peak concurrent connections, leaving enough headroom to surface scaling limits before real traffic does. If you anticipate a few hundred charge points in production, simulate a sizable multiple of that figure rather than matching it one-to-one. OCPPLab supports 10,000+ concurrent charge points. Achieving similar scale with OCPP.js requires significant custom engineering. The other tools in this comparison are not designed for load testing. ### Do I need to test both OCPP 1.6 and 2.0.1? If your CPMS supports both versions (which it should, given the installed base of 1.6 chargers and the industry migration to 2.0.1), then yes, you need to test both. A common approach is to run separate test suites for each version and verify that your CPMS handles version negotiation correctly during the WebSocket connection handshake. See our detailed comparison of [OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1) for protocol-level differences. ### What is the difference between a simulator and an emulator? In the OCPP context, the terms are often used interchangeably, but there is a meaningful distinction. A **simulator** generates OCPP messages that mimic charge point behavior without replicating the internal state machine. An **emulator** replicates the full charge point behavior including state transitions, error handling, and protocol timing. For CPMS testing, emulation provides more realistic results because it exposes bugs that only manifest when charge points behave according to the full state model. OCPPLab uses emulation for this reason. ## Further Reading - [The Complete OCPP Testing Guide](/blog/ocpp-testing-guide) -- strategies, tools, and best practices for building a robust OCPP test suite. - [Virtual vs Physical Testing for EV Chargers](/blog/virtual-vs-physical-testing) -- when to use simulated charge points and when you need hardware. - [What Is OCPP?](/blog/what-is-ocpp) -- a primer on the Open Charge Point Protocol for teams new to the specification. - [OCPP WebSocket Communication Explained](/blog/ocpp-websocket-guide) -- how OCPP messages flow over WebSocket connections, and what to test at the transport layer. - [What Is a CPMS?](/blog/what-is-csms) -- understanding the Central System your testing tools connect to. --- ## OCPP Security Profiles Explained: TLS & Certificates Source: https://ocpplab.com/blog/ocpp-security-profiles-explained OCPP 2.0.1 defines three mandatory security profiles. Learn how Profiles 1, 2, and 3 handle TLS, certificate management, and mutual TLS authentication. **Quick answer:** OCPP 2.0.1 defines three mandatory security profiles. **Profile 1** is HTTP Basic Auth over unencrypted `ws://` (only for isolated networks). **Profile 2** is HTTP Basic Auth over TLS `wss://` with server certificate validation — the practical minimum for production. **Profile 3** is mutual TLS (mTLS) where both the charger and CPMS authenticate with X.509 certificates — the strongest option, recommended for public infrastructure. OCPP 1.6 supports the same profile model (numbered 0–3) as an opt-in extension via the **Security Whitepaper edition 2**. Every EV charge point is a network-connected computer that processes payment data, controls high-voltage equipment, and communicates with backend systems over the public internet. A compromised charger is not a theoretical risk --- it is a physical safety hazard, a payment fraud vector, and a potential entry point into an operator's entire network. OCPP 2.0.1 introduced mandatory security profiles specifically because the previous generation of the protocol left security as an afterthought, and the industry paid for it. This guide covers the three OCPP 2.0.1 security profiles in detail: what each one provides, how they work at the protocol level, when to use each, and how to implement and test them correctly. > **Note on OCPP 1.6:** A similar profile-based security model was retroactively added to OCPP 1.6 through the **Security Whitepaper edition 2** (Profiles 0/1/2/3, plus certificate management, signed firmware, and `SecurityEventNotification`). The whitepaper is opt-in per deployment, so most of the installed 1.6 base still runs without it. OCPP 2.0.1's contribution is making the model **mandatory** and unifying the numbering — not inventing the profile concept itself. ## What Was the Security Problem in OCPP 1.6? The original [OCPP 1.6](/blog/what-is-ocpp) core specification treated security as optional. It mentioned TLS but did not mandate it, define authentication mechanisms, or provide any certificate management framework. The Security Whitepaper edition 2 later filled most of those gaps for 1.6 as an opt-in extension, but it was published years after 1.6 itself and is not present in every deployed charger. In practice, the core-only posture led to widespread vulnerabilities across production charging networks. ### What went wrong **Unencrypted WebSocket connections in production.** Independent security researchers have repeatedly documented OCPP 1.6 deployments running over unencrypted `ws://` rather than `wss://`. In 2021, [Pen Test Partners disclosed vulnerabilities](https://www.pentestpartners.com/security-blog/smart-car-chargers-plug-n-play-for-hackers/) (Pen Test Partners, "Smart car chargers. Plug-n-play for hackers?", 2021) across six EV charger brands — including chargers with no authentication and predictable device IDs affecting millions of devices. When `ws://` is used, every message --- including charger credentials, transaction data, and configuration commands --- travels in plaintext, and anyone on the same network segment can read and modify these messages. **No standardized authentication.** OCPP 1.6 does not define how a CPMS should verify that an incoming [WebSocket connection](/blog/ocpp-websocket-guide) actually comes from a legitimate charge point. Many implementations rely solely on the charger's serial number in the URL path (`/ocpp/CP001`), which is trivially spoofable. **No firmware signing.** When a CPMS pushes a firmware update to a charger over OCPP 1.6, there is no mechanism to verify the firmware's authenticity. An attacker who can intercept or modify the firmware URL can push arbitrary code to the charge point. **Man-in-the-middle exposure.** Without TLS, an attacker positioned between the charger and the CPMS can intercept messages, inject fraudulent transaction data, modify charging profiles, or issue remote commands to the charger --- including stopping or starting sessions, changing power limits, or resetting the device. ### Real-world risk scenarios These are not hypothetical. Publicly documented incidents and security research have demonstrated: - **Session hijacking**: Spoofing a charger identity to report phantom transactions or steal revenue from legitimate sessions. - **Free charging fraud**: Manipulating transaction messages to avoid billing. - **Charger bricking**: Pushing malicious firmware that renders charge points inoperable, requiring physical truck rolls to recover. - **Network lateral movement**: Using a compromised charge point as a pivot to access the operator's internal systems, including payment processing and customer databases. The Open Charge Alliance recognized these risks and made security a first-class concern in OCPP 2.0.1. ## What Are the OCPP 2.0.1 Security Profiles? OCPP 2.0.1 defines three security profiles that provide progressively stronger authentication and encryption. Every conformant implementation must support at least one profile, and the specification strongly recommends Profile 2 or 3 for any internet-facing deployment. The profile model is normative in the [OCPP 2.0.1 specification published by the Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), and the equivalent model for OCPP 1.6 lives in the [OCPP 1.6 Security Whitepaper edition 2](https://openchargealliance.org/protocols/open-charge-point-protocol/) (also from OCA). | | **Profile 1** | **Profile 2** | **Profile 3** | |---|---|---|---| | **Authentication** | HTTP Basic Auth | HTTP Basic Auth | Mutual TLS (client certificate) | | **Transport Encryption** | None (`ws://`) | TLS (`wss://`) | TLS (`wss://`) | | **Server Identity Verification** | None | Server certificate validated by charger | Server certificate validated by charger | | **Client Identity Verification** | Password in HTTP header | Password in HTTP header | Client certificate validated by server | | **Certificate Management** | Not applicable | Server certificate only | Server + client certificates | | **Protection Against MITM** | None | Yes (server authenticated) | Yes (both sides authenticated) | | **Recommended Use Case** | Isolated private networks | Standard production deployments | High-security and regulated environments | The profile is configured on the charge point via the `SecurityProfile` variable in the Security component, and the CPMS must be configured to accept connections at the corresponding security level. ## What Is Security Profile 1 (Basic Authentication)? Security Profile 1 provides the minimum level of identity verification: the charge point authenticates itself to the CPMS using HTTP Basic Authentication transmitted during the WebSocket handshake. No TLS encryption is used. ### How it works 1. The charge point initiates a WebSocket connection to the CPMS at a `ws://` endpoint. 2. The HTTP Upgrade request includes an `Authorization` header containing the Base64-encoded `chargePointId:password` string. 3. The CPMS decodes the credentials, validates them against its database, and either accepts the WebSocket upgrade or rejects it with HTTP 401. 4. All subsequent OCPP messages travel over the unencrypted WebSocket connection. ### Password management The charger's authentication password is configured via the `BasicAuthPassword` variable. OCPP 2.0.1 specifies that passwords must be at least 16 characters and should be rotated periodically. The CPMS can trigger a password change by sending a `SetVariables` request to update the `BasicAuthPassword`, after which the charger reconnects with the new credentials. ### When to use Profile 1 Profile 1 is appropriate only when: - The charger and CPMS communicate over a physically isolated private network (e.g., a dedicated VPN or private APN on a cellular connection). - No sensitive data traverses the connection, or the network itself provides encryption at a lower layer. - Regulatory requirements do not mandate transport-layer encryption. In every other scenario, Profile 1 is insufficient. The password travels in Base64 encoding (not encryption) and is visible to any network observer. Do not use Profile 1 over the public internet. ### Risks - All traffic is plaintext --- credentials, transaction data, and commands are fully exposed. - Susceptible to credential theft via packet capture. - No protection against man-in-the-middle attacks. - An attacker who captures the password can impersonate the charger indefinitely until the password is rotated. ## What Is Security Profile 2 (TLS with Server Certificate)? Security Profile 2 adds TLS encryption to the Basic Authentication mechanism. The charger verifies the CPMS server's identity via its TLS certificate, and all communication is encrypted. This is the recommended minimum for any production deployment. ### How it works 1. The charge point initiates a TLS handshake with the CPMS at a `wss://` endpoint. 2. The CPMS presents its server certificate. The charger validates the certificate against its trusted root certificate store (the `CACertificateStore` or a pre-provisioned root CA). 3. Once the TLS session is established, the charger sends the HTTP Upgrade request with the `Authorization` header containing Basic Auth credentials, just as in Profile 1 --- but now encrypted within the TLS tunnel. 4. The CPMS validates the credentials and accepts or rejects the connection. 5. All subsequent OCPP messages travel over the encrypted WebSocket connection. ### TLS configuration requirements OCPP 2.0.1 specifies concrete requirements for the TLS configuration: **Minimum TLS version**: TLS 1.2 is the minimum. TLS 1.3 is recommended where both sides support it. TLS 1.0 and 1.1 are explicitly prohibited. **Cipher suites**: The specification recommends cipher suites providing forward secrecy. Acceptable examples include: - `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` - `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` - `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` - `TLS_AES_128_GCM_SHA256` (TLS 1.3) - `TLS_AES_256_GCM_SHA384` (TLS 1.3) Cipher suites without forward secrecy (e.g., RSA key exchange) or using CBC mode should be disabled. **Certificate requirements**: The server certificate must be a valid X.509v3 certificate. The charger validates the certificate chain up to a trusted root CA. The certificate's Common Name (CN) or Subject Alternative Name (SAN) must match the CPMS hostname. ### Certificate provisioning For Profile 2, you need to provision the charger with the root CA certificate that signed the CPMS server certificate. This can be done: - **At manufacturing**: Pre-load the charger with a set of trusted root CAs (similar to how browsers ship with trusted roots). - **During commissioning**: Install the root CA certificate via a local interface or initial unencrypted connection, then switch to Profile 2. - **Via OCPP**: Use the `InstallCertificate` message to push the root CA certificate to the charger (though this requires an already-established connection). ### When to use Profile 2 Profile 2 is appropriate for: - Standard production deployments over the public internet. - Environments where the CPMS identity must be verified but individual charger certificate management is operationally burdensome. - Deployments where HTTP Basic Auth provides sufficient client authentication for the threat model. Profile 2 protects against network eavesdropping and server impersonation. It does not protect against a stolen charger password being used from a different device --- the CPMS cannot distinguish between the real charger and an attacker using the same credentials from a different machine. ## What Is Security Profile 3 (Mutual TLS)? Security Profile 3 is the gold standard. Both the charger and the CPMS authenticate each other using X.509 certificates. No passwords are involved --- identity is proven cryptographically. ### How it works 1. The charge point initiates a TLS handshake with the CPMS at a `wss://` endpoint. 2. The CPMS presents its server certificate. The charger validates it against its trusted root CA store. 3. The CPMS requests the client certificate. The charger presents its own X.509 certificate. 4. The CPMS validates the charger's certificate against its trusted root CA store. If the certificate is valid and not revoked, the TLS handshake completes. 5. The WebSocket upgrade proceeds without an `Authorization` header --- the TLS client certificate has already authenticated the charger. 6. All communication is encrypted and both endpoints are cryptographically verified. ### Why mTLS is stronger With Profile 2, a stolen password can be used from any device. With Profile 3, the charger's private key never leaves the device. Even if an attacker captures network traffic, they cannot extract the private key from the TLS handshake. To impersonate a charger, an attacker would need physical access to extract the private key from the device's secure storage --- a significantly higher barrier. mTLS also eliminates the operational burden of password management. There are no passwords to rotate, no risk of weak passwords, and no credentials transmitted in HTTP headers. ### PKI requirements Profile 3 requires a functioning Public Key Infrastructure (PKI): **Certificate Authority (CA)**: You need a CA to issue certificates to both the CPMS and individual charge points. This can be: - A **private CA** operated by the CPO or CPMS vendor (most common for charge point certificates). - A **public CA** like [Let's Encrypt](https://letsencrypt.org/) or DigiCert for the CPMS server certificate. - A **managed PKI service** from a cloud provider (AWS Private CA, Azure Key Vault, Google Cloud CA Service). **Certificate lifecycle**: Each charge point needs its own unique certificate. This means provisioning certificates at manufacturing or commissioning, rotating them before expiry, and revoking them if a device is decommissioned or compromised. **Secure key storage**: The charger must store its private key in a secure element or trusted platform module (TPM) to prevent extraction. The specification recommends hardware-backed key storage. ### When to use Profile 3 Profile 3 is appropriate for: - High-security deployments in regulated industries (government facilities, military installations, critical infrastructure). - Networks where charger impersonation is a material threat. - Operators who have the infrastructure to manage a PKI and certificate lifecycle. - Deployments that require compliance with standards like [ISO 15118 Plug & Charge](/blog/iso-15118-plug-and-charge), which also relies on certificate-based authentication. The primary barrier to Profile 3 adoption is operational complexity. Managing certificates for thousands of charge points requires automation, monitoring for approaching expiry dates, and a revocation strategy. For many operators, Profile 2 provides sufficient security with significantly less operational overhead. ## How Does Certificate Management Work in OCPP 2.0.1? OCPP 2.0.1 includes dedicated messages for managing certificates on charge points over the OCPP connection itself. This is critical for Profile 2 and Profile 3 deployments where certificates need to be updated remotely. ### InstallCertificate The CPMS sends `InstallCertificate` to push a new certificate to the charge point. The message specifies the certificate type: - `CentralSystemRootCertificate` --- Root CA used to validate the CPMS server certificate. - `ManufacturerRootCertificate` --- Root CA used to validate firmware signing certificates. - `V2GRootCertificate` --- Root CA for [ISO 15118](https://www.iso.org/standard/55366.html) Vehicle-to-Grid communication. The charger validates the certificate format and stores it. If storage is full or the certificate is malformed, the charger responds with `Rejected`. ### GetInstalledCertificateIds The CPMS sends `GetInstalledCertificateIds` to query which certificates are currently installed on the charger. The response includes the certificate hash (issuer name hash, issuer key hash, serial number) for each installed certificate. This allows the CPMS to audit a charger's certificate store and determine if updates are needed. ### DeleteCertificate The CPMS sends `DeleteCertificate` to remove a specific certificate from the charge point, identified by its certificate hash data. This is used to revoke trust in a compromised CA or remove expired certificates. ### CertificateSigningRequest For Profile 3, when a charger needs a new client certificate (initial provisioning or renewal), it generates a key pair locally and sends a `SignCertificate` request containing the CSR (Certificate Signing Request). The CPMS forwards the CSR to the CA, obtains the signed certificate, and delivers it back to the charger via `CertificateSigned`. This ensures the private key is generated on the charger and never transmitted. ### Certificate rotation workflow A typical certificate renewal for Profile 3 follows this sequence: 1. The CPMS monitors certificate expiry dates (queried via `GetInstalledCertificateIds`). 2. Before expiry, the CPMS triggers the charger to generate a new CSR via `TriggerMessage` with `SignCertificate`. 3. The charger generates a new key pair and sends `SignCertificate` with the CSR. 4. The CPMS submits the CSR to the CA and receives the signed certificate. 5. The CPMS sends `CertificateSigned` with the new certificate. 6. The charger installs the new certificate and begins using it on the next TLS handshake. This entire workflow happens over the existing OCPP connection without physical access to the charger. ## How Do Signed Firmware Updates Work? OCPP 2.0.1 addresses the firmware tampering risk from OCPP 1.6 with cryptographic signature verification for firmware updates. ### How signed firmware works 1. The CPMS sends a `SignedUpdateFirmware` request containing the firmware download URL, the expected signing certificate, and the firmware signature. 2. The charger downloads the firmware from the specified URL. 3. Before installing, the charger verifies the firmware signature against the signing certificate. The signing certificate itself is validated against the `ManufacturerRootCertificate` installed on the charger. 4. If the signature is valid, the charger installs the firmware and reports `Installed` via `FirmwareStatusNotification`. 5. If verification fails, the charger rejects the update and reports `InvalidSignature`. ### Secure boot chain Signed firmware is most effective when combined with secure boot: 1. **Hardware root of trust**: The bootloader is stored in read-only memory and cannot be modified. 2. **Chain of trust**: The bootloader verifies the OS image signature before loading it. The OS verifies application firmware signatures before executing. 3. **Runtime integrity**: The charge point periodically verifies its own firmware integrity and reports anomalies. Together, signed firmware and secure boot ensure that only authorized code runs on the charge point, from power-on through normal operation. ## Implementation Recommendations ### Choosing the right profile **Start with Profile 2** for most deployments. It provides encrypted communication and server authentication with manageable operational complexity. The majority of production OCPP 2.0.1 networks run Profile 2. **Use Profile 3** when: - Your threat model specifically includes charger impersonation. - Regulatory requirements mandate mutual authentication. - You are deploying ISO 15118 Plug & Charge (which requires its own certificate infrastructure, making the incremental cost of mTLS lower). - You have or can build the PKI infrastructure to manage per-device certificates. **Avoid Profile 1** for internet-facing deployments. If you must use it, ensure the network provides encryption at a lower layer (IPsec VPN, private APN with encryption). ### TLS setup checklist For Profile 2 and 3 deployments: 1. **Obtain a server certificate** from a public CA for your CPMS endpoint. Use a SAN that matches your WebSocket URL hostname. 2. **Configure TLS 1.2 minimum** on your CPMS. Disable TLS 1.0, 1.1, and all weak cipher suites. 3. **Enable forward secrecy** by prioritizing ECDHE cipher suites. 4. **Provision chargers with the root CA certificate** that signs your server certificate. For public CAs, most charger firmware includes standard root stores. 5. **Implement OCSP stapling** or CRL checking on the CPMS to enable certificate revocation validation. 6. **Monitor certificate expiry** and automate renewal. A single expired certificate can take down connectivity for your entire fleet. ### Certificate authority options | Approach | Pros | Cons | Best for | |----------|------|------|----------| | **Public CA** (Let's Encrypt, DigiCert) | Trusted by default, automated renewal (ACME), no infrastructure to run | Cannot issue client certificates for charge points (typically), cost per certificate at scale | CPMS server certificates | | **Private CA** (self-hosted, e.g., step-ca, EJBCA) | Full control, no per-certificate cost, can issue client certificates | Requires operational expertise, must distribute root CA to all chargers | Charge point client certificates for Profile 3 | | **Managed PKI** (AWS Private CA, Azure Key Vault) | Managed infrastructure, API-driven, audit logging | Per-certificate cost, cloud vendor dependency | Organizations without PKI expertise | For most operators, a hybrid approach works well: public CA for the CPMS server certificate (Profile 2) and private or managed CA for charge point client certificates (Profile 3). ## How to Test OCPP Security Profiles Security configuration is one of the most common sources of interoperability issues in OCPP deployments. A charger that works perfectly on an unencrypted connection may fail silently when TLS is enabled due to certificate chain issues, cipher suite mismatches, or incorrect hostname validation. ### What to test **Profile 1 testing:** - Verify the charger sends correct Basic Auth credentials in the WebSocket upgrade request. - Test with incorrect passwords --- the CPMS should reject with HTTP 401. - Confirm password rotation works: update `BasicAuthPassword` via `SetVariables`, verify the charger reconnects with the new password. **Profile 2 testing:** - Verify TLS handshake completes successfully with a valid server certificate. - Test with an expired server certificate --- the charger should refuse to connect. - Test with a self-signed certificate not in the charger's trust store --- connection should fail. - Verify cipher suite negotiation uses forward-secrecy suites. - Test `InstallCertificate` for updating the root CA on the charger. - Confirm the charger validates the server certificate's hostname against the connection URL. **Profile 3 testing:** - Verify mutual TLS handshake with valid client and server certificates. - Test with a revoked client certificate --- the CPMS should reject the connection. - Test the full `SignCertificate` / `CertificateSigned` workflow for certificate provisioning. - Verify certificate rotation without connection downtime. - Test `GetInstalledCertificateIds` to audit the charger's certificate store. - Confirm `DeleteCertificate` correctly removes certificates and the charger stops trusting the deleted CA. **Firmware signing testing:** - Send a `SignedUpdateFirmware` with a valid signature --- firmware should install. - Send a `SignedUpdateFirmware` with a tampered signature --- charger should reject with `InvalidSignature`. - Test with an expired signing certificate. ### Testing with OCPPLab [OCPPLab](/) provides an OCPP emulator that supports all three security profiles, allowing you to test your CPMS or charge point firmware against each profile configuration without deploying physical hardware. You can simulate TLS connections, certificate exchanges, and the full certificate lifecycle management workflow, catching configuration issues before they reach production. For a broader overview of OCPP testing strategies and tools, see our [OCPP testing guide](/blog/ocpp-testing-guide). ## Frequently Asked Questions ### Is OCPP 2.0.1 security mandatory? Yes. Every OCPP 2.0.1 implementation must support at least one security profile. The specification does not allow unprotected connections without a declared profile. However, the choice of which profile to implement is left to the deployer. In practice, conformance testing programs from the OCA verify security profile support. ### Can I upgrade from Profile 1 to Profile 2 or 3 remotely? Yes, but with caveats. You can push a root CA certificate via `InstallCertificate` over an existing Profile 1 connection, then change the `SecurityProfile` variable to 2 via `SetVariables`. The charger will reconnect using TLS. Upgrading to Profile 3 requires provisioning a client certificate, which involves the `SignCertificate` workflow. The initial Profile 1 connection is unencrypted, so this upgrade path should ideally happen on a trusted network during commissioning. ### What happens if a charger's certificate expires? If a Profile 3 charger's client certificate expires, the CPMS will reject the TLS handshake and the charger will be unable to connect. This is why proactive certificate monitoring and renewal is critical. Most implementations trigger renewal 30-60 days before expiry. If a certificate does expire, the charger typically requires a local intervention (physical access or local API) to install a new certificate or temporarily downgrade to Profile 2 with Basic Auth to re-establish connectivity. ### Do I need a separate PKI for OCPP and ISO 15118? They are technically separate trust chains. The OCPP PKI handles charger-to-CPMS authentication. The ISO 15118 PKI (V2G PKI) handles vehicle-to-charger authentication for Plug & Charge. However, some operators share infrastructure components (the same CA software, HSMs, and monitoring tools) between the two PKIs to reduce operational costs. The root certificates are distinct and installed via different certificate types in `InstallCertificate`. ### How does OCPP security relate to PCI DSS compliance? OCPP security profiles help meet PCI DSS requirements for encrypting cardholder data in transit, but they are not sufficient on their own. PCI DSS covers the entire payment processing chain, including data storage, access controls, and network segmentation. Profile 2 or 3 addresses the transport encryption requirement between the charger and CPMS. Additional measures are needed for end-to-end payment security. ### Can I use Let's Encrypt certificates for my CPMS? Yes, and many operators do. Let's Encrypt certificates are trusted by most charger firmware out of the box (since chargers typically ship with standard root CA stores). The 90-day validity requires automated renewal via ACME, which is straightforward for server-side certificates. Let's Encrypt does not issue client certificates, so you will need a separate CA for Profile 3 charge point certificates. ## Further Reading - [What is OCPP? The Complete Guide](/blog/what-is-ocpp) --- Foundational overview of the protocol, message types, and architecture. - [OCPP 1.6 vs 2.0.1: Complete Comparison](/blog/ocpp-1-6-vs-2-0-1) --- Detailed comparison including security, smart charging, and migration guidance. - [OCPP WebSocket Guide](/blog/ocpp-websocket-guide) --- Deep dive into WebSocket connection management, TLS configuration, and reconnection strategies. - [OCPP Testing Guide](/blog/ocpp-testing-guide) --- Comprehensive guide to testing OCPP implementations, including security profile validation. --- ## OCPI vs OICP vs OCHP: EV Charging Roaming Protocols Compared Source: https://ocpplab.com/blog/ocpi-vs-oicp-vs-ochp Compare OCPI vs OICP vs OCHP, the 3 main EV charging roaming protocols, by architecture, adoption, and Plug&Charge support so you can pick the right standard. **Quick answer:** OCPI, OICP, and OCHP are the three main EV charging roaming protocols. OCPI is the open, most widely adopted standard governed by the EVRoaming Foundation and is the default choice for new networks. OICP is Hubject's proprietary protocol, strong in DACH markets. OCHP is an older, declining protocol now largely superseded by OCPI. OCPI, OICP, and OCHP are the three main protocols for EV charging roaming — enabling drivers to charge on networks they don't subscribe to. **OCPI (Open Charge Point Interface)** is the most widely adopted open protocol, governed by the EVRoaming Foundation. **OICP (Open InterCharge Protocol)** is Hubject's proprietary protocol, tightly coupled to their eRoaming platform. **OCHP (Open Clearing House Protocol)** is an older open protocol, originally developed for e-clearing.net, now largely superseded by OCPI in most new implementations. Choosing the right roaming protocol — or combination of protocols — has real consequences for your integration timeline, partner reach, and long-term flexibility. This guide breaks down the technical and strategic differences so you can make an informed decision. If you need partner-readiness validation before live onboarding, start with [GIREVE OCPI testing](/integrations/gireve-ocpi-testing) or [Hubject OICP testing](/integrations/hubject-oicp-testing). ## Quick Comparison Table | Feature | OCPI | OICP | OCHP | |---------|------|------|------| | **Governance** | Open (EVRoaming Foundation) | Proprietary (Hubject) | Open (e-clearing.net / ElaadNL) | | **Latest Version** | 2.2.1 (3.0 in development) | 2.3 | 1.4 | | **Protocol Type** | REST API (JSON) | REST API (JSON), formerly SOAP | SOAP (XML) | | **Adoption** | Widely adopted across Europe, expanding globally | Large network, strong across many countries | Limited and declining | | **Primary Hub** | GIREVE, also supported by others | Hubject (intercharge) | e-clearing.net | | **Geographic Strength** | Europe-wide, expanding globally | Germany, Austria, strong in Asia-Pacific | Western Europe (legacy) | | **Pricing Module** | Full tariff module with complex pricing | Pricing supported via hub | Basic pricing support | | **Session Management** | Real-time session data exchange | Session management via hub APIs | Limited session exchange | | **Plug&Charge (ISO 15118)** | Supported in 2.2.1+ | Native support via Hubject PKI | Not supported | | **Smart Charging** | Charging preferences in 2.2.1 | Limited | Not supported | | **Community / Docs** | Large open community, public spec | Public spec, platform access via Hubject | Small community, public spec | | **Specification Access** | Freely available on GitHub | Published on GitHub; network access via Hubject | Freely available | ## What Is OCPI, the Open Standard? ### Overview OCPI is developed and maintained by the **[EVRoaming Foundation](https://evroaming.org/)**, a Dutch non-profit backed by major European CPOs and eMSPs. The specification is open-source, hosted [publicly on GitHub](https://github.com/ocpi/ocpi), and anyone can implement it without licensing fees or partnership agreements. OCPI uses a straightforward **REST API with JSON payloads**. If you've built any modern web API, the architecture will be immediately familiar. Each party hosts its own OCPI endpoints, and data exchange happens through standard HTTP methods. ### Key Technical Characteristics **Modular architecture**: OCPI 2.1.1 is divided into six independent modules — Locations, Sessions, CDRs, Tariffs, Tokens, and Commands. OCPI 2.2.1 adds two more: ChargingProfiles and HubClientInfo. You implement only the modules you need. A CPO publishing charger locations doesn't need to implement the Commands module if they don't support remote start. **Peer-to-peer or hub-based**: OCPI supports both direct bilateral connections between parties and connections through roaming hubs. In practice, most companies connect through a hub like [GIREVE](/blog/gireve-hub-integration) to avoid maintaining dozens of individual connections. **Pull and Push**: Data can be pulled on demand or pushed in real-time. Locations data, for example, can be pulled in bulk during initial sync and then pushed incrementally as availability changes. ### Versions in the Wild - **OCPI 2.1.1** remains the most widely deployed version. It covers all core roaming functionality and is supported by every major hub. - **OCPI 2.2.1** adds hub-specific features, charging preferences, improved tariff structures, and better error handling. Newer implementations increasingly target 2.2.1. - **OCPI 3.0** is under development and will introduce breaking changes, including a redesigned module structure and improved real-time capabilities. For a deeper dive into OCPI's architecture and modules, see our complete guide: [What is OCPI?](/blog/what-is-ocpi) ### Strengths - Fully open specification with no vendor lock-in - Largest and most active developer community - Clean REST/JSON architecture that integrates easily with modern tech stacks - Supported by all major roaming hubs (GIREVE, Hubject, e-clearing.net) - Active development with a clear roadmap ### Limitations - Real-time capabilities in 2.1.1 are limited (improved in 2.2.1) - No built-in PKI infrastructure for Plug&Charge (relies on external certificate management) - The specification allows flexibility that can lead to inconsistent implementations between partners ## What Is OICP, Hubject's Protocol? ### Overview OICP is the protocol behind **[Hubject's intercharge network](https://hubject.com/)**, one of the largest EV roaming platforms globally. Although [Hubject publishes the OICP specification on GitHub](https://github.com/hubject/oicp), in practice OICP is closely tied to Hubject's platform — you implement it as part of a commercial relationship with Hubject. While the protocol documents are accessible, using OICP in production means onboarding onto Hubject's network rather than deploying independently or bilaterally. Hubject operates as a **centralized B2B platform**. All roaming data flows through Hubject's infrastructure. This means you don't establish direct connections with other CPOs or eMSPs — Hubject mediates every interaction. ### Key Technical Characteristics **Hub-centric architecture**: OICP is designed exclusively for hub-based communication. There is no peer-to-peer mode. Every authorization request, session record, and CDR passes through Hubject's platform. **Evolved from SOAP to REST**: Earlier versions of OICP used SOAP/XML, which added significant implementation complexity. Recent versions (2.3+) have migrated to REST/JSON, bringing the developer experience closer to OCPI. **Integrated Plug&Charge**: Hubject operates a **Public Key Infrastructure (PKI)** for ISO 15118 Plug&Charge. If Plug&Charge is a priority for your network, Hubject offers one of the most mature certificate management solutions in the industry. This is a genuine differentiator — managing a PKI independently is complex and expensive. **Built-in business services**: Beyond protocol-level data exchange, Hubject's platform includes business intelligence dashboards, partner discovery, and contract management. The protocol and the platform are deliberately intertwined. ### Strengths - Mature Plug&Charge / ISO 15118 PKI infrastructure - Strong market presence in Germany, Austria, and expanding in Asia-Pacific - Integrated business tools beyond raw data exchange - Large connected B2B partner network ### Limitations - Governed solely by Hubject — limited external community contribution compared to OCPI - Vendor lock-in: your roaming capability is tied to Hubject's platform and pricing - All data routes through Hubject's infrastructure (potential single point of failure, data sovereignty considerations) - Commercial fees for every roaming transaction - Less flexibility for custom integrations or direct bilateral agreements ## What Is OCHP, the Legacy Protocol? ### Overview OCHP was one of the earliest attempts at standardizing EV charging roaming. Developed for the **e-clearing.net** platform — a joint initiative by smartlab, ElaadNL, and other early European players — OCHP aimed to solve the same interoperability problem that OCPI and OICP address today. Its [specification and WSDL definitions remain on GitHub](https://github.com/e-clearing-net/OCHP). ### Key Technical Characteristics **SOAP-based**: OCHP uses SOAP with XML payloads. This was standard when the protocol was designed, but it means significantly more implementation overhead compared to REST/JSON approaches. WSDL definitions, XML schemas, and SOAP envelope handling add friction for development teams accustomed to modern API patterns. **Clearing house model**: OCHP was built specifically around the clearing house concept — a central party that handles authorization, session data, and financial settlement between CPOs and eMSPs. The protocol assumes this centralized topology. **Limited module scope**: OCHP covers the basics — charger data exchange (known as "charge point info"), authorization, and charge detail records. It lacks the richer module set found in OCPI (tariffs, commands, real-time sessions) and the platform services bundled with OICP. ### Current Status OCHP adoption has been declining steadily. Most organizations that originally implemented OCHP have either migrated to OCPI or added OCPI as a parallel interface. The e-clearing.net platform itself now supports OCPI alongside OCHP. New implementations of OCHP are rare. Unless you are integrating with a legacy partner that exclusively supports OCHP, there is little reason to implement it today. ### Strengths - Open specification - Proven in production for over a decade - Still supported by e-clearing.net ### Limitations - SOAP/XML adds significant development and maintenance overhead - Small and shrinking community - No Plug&Charge support - No smart charging features - Limited real-time session capabilities - Declining adoption means fewer potential roaming partners ## Which Protocol Should You Choose? The right choice depends on your specific situation. Here is a decision framework based on the factors that matter most. ### Geography If your charging network operates **primarily in Germany and Austria**, OICP gives you immediate access to the densest roaming network in that region. Hubject's market share in DACH countries is substantial. If you operate **anywhere else in Europe**, OCPI is the default choice. GIREVE, the largest European hub, uses OCPI as its primary protocol, and the majority of European CPOs and eMSPs have OCPI implementations. If you are **expanding into Asia-Pacific**, both OCPI and OICP have growing presence. Hubject has been particularly active in South Korea and Japan. OCPI adoption is growing in India and Southeast Asia. For **North America**, the roaming ecosystem is less mature, but OCPI is emerging as the preferred protocol as the market develops. ### Hub Preference Your hub choice often dictates your protocol: - **GIREVE** primarily uses OCPI. Connecting to GIREVE means implementing OCPI. - **Hubject** primarily uses OICP. Connecting to Hubject means implementing OICP (though they also accept OCPI). - **e-clearing.net** supports both OCHP and OCPI. New connections should use OCPI. See our [GIREVE Hub Integration Guide](/blog/gireve-hub-integration) for details on connecting to the largest European hub. ### Technical Preference If your team values **open specifications, REST APIs, and community-driven development**, OCPI is the natural fit. The spec is on GitHub. You can read it, file issues, and contribute. If your team values **an integrated platform with managed services** and is comfortable with a commercial vendor relationship, OICP through Hubject provides a more turnkey experience. ### Plug&Charge Requirements If ISO 15118 Plug&Charge is a hard requirement today, Hubject's PKI infrastructure gives you a head start. While OCPI 2.2.1 supports Plug&Charge data exchange, it doesn't provide the certificate management infrastructure — you would need to source that separately or build your own. ### Cost Considerations OCPI itself is free to implement. Your costs are integration development time and any hub fees (GIREVE, for example, charges connection fees). OICP comes with Hubject's commercial terms — partnership fees, per-transaction costs, and platform fees. The tradeoff is that you get a managed platform with business tooling included. ## Can You Support Multiple Protocols? Yes — and many organizations do. Supporting multiple protocols is common in the EV roaming ecosystem for several reasons: ### Hub-Mediated Translation Major roaming hubs act as protocol translators. When a [CPO](/blog/cpo-vs-emsp-explained) connected via OCPI needs to roam with an eMSP connected via OICP, the hub handles the translation. GIREVE and Hubject both support this kind of cross-protocol mediation. This means you don't necessarily need to implement every protocol yourself. By connecting to a hub that bridges protocols, you can reach partners on different protocols through a single integration. ### Multi-Hub Strategy Some larger networks connect to multiple hubs simultaneously — for example, GIREVE via OCPI and Hubject via OICP — to maximize their roaming reach. This requires implementing and maintaining two protocol integrations, but it provides the widest possible partner network. ### Practical Recommendation For most organizations, **start with OCPI**. It gives you the broadest reach with a single implementation, and every major hub supports it. Add OICP later if you need deeper Hubject integration or Plug&Charge PKI services. There is almost never a reason to implement OCHP for a new integration. ## How Do You Test Roaming Protocols? Testing roaming protocol implementations is challenging because it involves two-party communication with complex state machines. Common testing approaches include: **Sandbox environments**: Most hubs offer sandbox or staging environments for testing. GIREVE and Hubject both provide test platforms where you can validate your implementation against simulated partners. **Conformance testing**: The EVRoaming Foundation provides OCPI conformance tests. Hubject has its own certification process for OICP implementations. **Local simulation**: For development and debugging, you need a way to simulate the other party in a roaming exchange. This is where tools like **OCPPLab** come in — our emulator supports OCPI testing, letting you simulate CPO and eMSP endpoints locally so you can validate your implementation before connecting to a production hub. Testing roaming flows end-to-end — from driver authorization through session management to CDR settlement — requires simulating realistic scenarios across the full protocol lifecycle. Investing in proper test infrastructure early saves significant debugging time when you go live with real partners. For more on testing strategies, see our [OCPP Testing Guide](/blog/ocpp-testing-guide), which covers many of the same principles applicable to roaming protocol testing. ## Frequently Asked Questions ### Is OCPI replacing OICP and OCHP? OCPI is replacing OCHP in most implementations — that trend is clear and accelerating. OCPI is not replacing OICP, however. Hubject continues to develop OICP and has a large, growing network. The two protocols coexist, with hubs bridging between them. Think of it as two competing standards, not one replacing the other. ### Can I use OCPI without connecting to a hub? Yes. OCPI supports direct peer-to-peer connections between a CPO and an eMSP. However, managing dozens of bilateral connections becomes impractical at scale. Most organizations use a hub for the majority of their roaming partnerships and maintain direct connections only for high-volume strategic partners. ### What is the relationship between OCPP and OCPI? [OCPP](/blog/what-is-ocpp) manages communication between a charger and a backend system (CPMS). OCPI manages communication between backend systems for roaming. They operate at different layers: OCPP handles the physical charging infrastructure, while OCPI handles the business-to-business roaming layer. A typical CPO implements both — OCPP for their chargers and OCPI for their roaming connections. ### How long does it take to implement OCPI? A basic OCPI 2.2.1 implementation covering Locations, Tokens, Sessions, and CDRs typically takes several months for an experienced team. The timeline depends on your existing backend architecture, the number of modules you need, and whether you're integrating with a hub or establishing direct connections. Hub-specific requirements (credential exchange, registration flows) add additional time. ### Is OICP only available through Hubject? Yes. OICP is Hubject's protocol, and implementing it requires a partnership agreement with Hubject. You cannot use OICP independently of the Hubject platform. This is a fundamental architectural difference from OCPI, which is hub-agnostic. ### Which protocol has better documentation? OCPI's specification is publicly available on GitHub with detailed module descriptions, sequence diagrams, and examples. Community discussions and implementation guides are freely accessible. OICP's specification is also published on GitHub, but its surrounding community, third-party guides, and open discussion are far smaller. In terms of public resources and community support, OCPI has a significant advantage. ## Summary For new implementations, **OCPI is the default recommendation**. It is open, widely adopted, technically modern, and supported by every major roaming hub. Implement OICP in addition to OCPI if you need Hubject's Plug&Charge PKI or deeper access to the DACH and Asia-Pacific markets. Avoid OCHP unless you have a specific legacy integration requirement. The EV charging roaming ecosystem is maturing rapidly. Protocols are converging around REST/JSON architectures, hubs are bridging across protocols, and the driver experience is becoming increasingly seamless. Whichever protocol you choose, the important thing is to start — roaming capability is quickly becoming table stakes for any serious charging network. --- **Related reading:** - [What is OCPI? Open Charge Point Interface Explained](/blog/what-is-ocpi) - [GIREVE Hub Integration Guide](/blog/gireve-hub-integration) - [CPO vs eMSP: Roles in EV Charging Explained](/blog/cpo-vs-emsp-explained) - [What is OCPP? Open Charge Point Protocol Explained](/blog/what-is-ocpp) --- ## What Is OCPP? Open Charge Point Protocol Explained Source: https://ocpplab.com/blog/what-is-ocpp What OCPP is, how the Open Charge Point Protocol works, and what EV charging teams must know about OCPP 1.6, 2.0.1, message flows, security, and testing. **Quick answer:** OCPP (Open Charge Point Protocol) is an open WebSocket-based protocol from the [Open Charge Alliance](https://www.openchargealliance.org/) that lets EV chargers communicate with a backend platform (a CPMS). It standardizes how a charger registers, authorizes users, runs transactions, reports meter values, and applies smart charging — across vendors. The two production versions are **OCPP 1.6** (the most widely deployed) and **OCPP 2.0.1** (the modern standard with mandatory security profiles, a device model, and ISO 15118 support). OCPP (Open Charge Point Protocol) is the standard that lets EV chargers communicate with a backend platform — the **Central System** in OCPP 1.6, the **CSMS** (Charging Station Management System) in OCPP 2.0.1. Operators often call that backend a [CPMS (Charge Point Management System)](/blog/what-is-csms); that expansion is industry slang, not the 2.0.1 spec term. Maintained by the Open Charge Alliance (OCA), OCPP allows chargers from different manufacturers to connect to compatible software without proprietary lock-in, which is why it underpins most modern EV charging networks. As of 2024, the [Open Charge Alliance](https://openchargealliance.org/) counts more than 400 member organizations worldwide, and every major charger manufacturer --- ABB, Schneider Electric, EVBox, Wallbox, Alfen, Tritium, Kempower, and Autel --- ships hardware with OCPP support built in. The specifications themselves run to several hundred pages: per the [OCPP specification published by the OCA](https://openchargealliance.org/protocols/open-charge-point-protocol/), **OCPP 1.6 Edition 2** defines **28 unique core actions** (10 charger-initiated, 19 CPMS-initiated counting `DataTransfer` once) plus **11 more in the Security Whitepaper edition 2**, while **OCPP 2.0.1** reorganizes and substantially expands the message set across **16 functional blocks** (labelled A through P), covering many more messages than 1.6. If you are evaluating implementation or QA work right now, go straight to [OCPP 1.6 testing](/protocols/ocpp-1-6), [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1), or [platform features](/features). ## Why Does OCPP Exist? Before OCPP, every EV charger manufacturer built proprietary communication protocols. A ChargePoint station could only talk to ChargePoint's backend. An ABB charger required ABB's software. This created four systemic problems: - **Vendor lock-in**: Operators were permanently tied to a single manufacturer's ecosystem for both hardware and software. - **No interoperability**: Running a mixed-brand charging network was either impossible or required expensive custom integrations for each charger model. - **High integration costs**: Every new charger model demanded months of bespoke protocol development, driving up costs for CPMS vendors. - **Slow innovation**: Closed systems meant features developed by one vendor stayed siloed, and the industry moved slowly as a result. The [Open Charge Alliance (OCA)](https://www.openchargealliance.org/), founded in 2014 in the Netherlands, created OCPP to solve these problems with a single, open, royalty-free standard. The specifications are freely available from the OCA at [openchargealliance.org/protocols/open-charge-point-protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/). Today, OCPP is mandated or strongly encouraged by public funding programs across the EU, UK, and parts of the United States (notably California's NEVI program), making it the de facto global standard for EV charger communication. ## How Does OCPP Work? OCPP operates on a client-server architecture where the charge point (the physical charger) acts as the client and the CPMS acts as the server. Communication flows over persistent WebSocket connections, enabling real-time bidirectional messaging between charger and backend. ### Connection Lifecycle The WebSocket connection lifecycle follows a predictable pattern: 1. **DNS resolution and TCP handshake**: The charger resolves the CPMS hostname and establishes a TCP connection to the configured endpoint (typically `wss://CPMS.example.com/ocpp/`). 2. **TLS negotiation** (if using `wss://`): The charger and server negotiate a secure TLS session. OCPP 2.0.1 defines three specific security profiles governing this step. 3. **WebSocket upgrade**: The charger sends an HTTP Upgrade request with `Sec-WebSocket-Protocol: ocpp1.6` or `ocpp2.0.1`. The server validates the charger's identity (often from the URL path, e.g., `/ocpp/CP001`) and accepts or rejects the upgrade. 4. **BootNotification**: Immediately after the WebSocket is established, the charger sends a `BootNotification` message containing its vendor, model, serial number, and firmware version. The CPMS responds with `Accepted`, `Pending`, or `Rejected` along with a heartbeat interval. 5. **Steady-state communication**: Both sides exchange messages over the persistent connection. The charger sends periodic `Heartbeat` messages to confirm connectivity. Either side can initiate requests at any time. 6. **Reconnection**: If the connection drops, the charger automatically reconnects using configurable retry logic with exponential backoff. For a deep dive into WebSocket connection management, error handling, and reconnection strategies, see our [OCPP WebSocket guide](/blog/ocpp-websocket-guide). ### Request-Response Pattern Every OCPP interaction follows a strict request-response pattern using JSON-RPC-style framing over WebSocket. Messages are JSON arrays with a specific structure: **Call (Request)**: ```json [2, "unique-message-id", "BootNotification", {"chargePointVendor": "OCPPLab", "chargePointModel": "Emulator"}] ``` - `2` = Message type (Call) - `"unique-message-id"` = Unique identifier for correlation - `"BootNotification"` = Action name - `{...}` = Payload **CallResult (Successful Response)**: ```json [3, "unique-message-id", {"status": "Accepted", "currentTime": "2025-02-20T10:00:00Z", "interval": 300}] ``` - `3` = Message type (CallResult) - Same message ID as the originating Call - `{...}` = Response payload **CallError (Error Response)**: ```json [4, "unique-message-id", "FormationViolation", "Invalid payload", {}] ``` - `4` = Message type (CallError) - Standard error codes like `NotImplemented`, `NotSupported`, `InternalError`, `ProtocolError`, `SecurityError`, and `FormationViolation` Each side can only have one outstanding request at a time per the specification (though some implementations relax this). A request must receive a response within a configurable timeout, typically 30 seconds. ## OCPP Versions: A Complete History The protocol has evolved through several versions, each addressing limitations of its predecessor: | Version | Year | Transport | Status | |---------|------|-----------|--------| | OCPP 1.2 | 2010 | SOAP/XML | Legacy, rarely seen | | OCPP 1.5 | 2012 | SOAP/XML | Legacy, still in some older deployments | | OCPP 1.6 | 2015 | SOAP or WebSocket/JSON | Most widely deployed version globally. OCPPLab implements this | | OCPP 2.0 | 2018 | WebSocket/JSON | Superseded by 2.0.1, never widely adopted | | OCPP 2.0.1 | 2020 | WebSocket/JSON | Dominant 2.x production version. OCPPLab implements this | | OCPP 2.1 | 2025 | WebSocket/JSON | Published OCA spec (ISO 15118-20 / V2G-oriented). OCPPLab does not implement it | For a detailed feature-by-feature comparison, see our dedicated [OCPP 1.6 vs 2.0.1 comparison](/blog/ocpp-1-6-vs-2-0-1). If you are evaluating tooling rather than protocol features, see [best OCPP emulators compared](/blog/best-ocpp-emulators-compared). ### OCPP 1.6 Released in 2015, OCPP 1.6 remains the most widely deployed version in the field by a wide margin. It introduced JSON over WebSocket as a transport option alongside the original SOAP/XML format, which dramatically simplified implementations. Key capabilities of OCPP 1.6: - **Smart Charging**: Basic charging profile management with `SetChargingProfile` and `ClearChargingProfile` - **Remote Operations**: Start and stop transactions remotely, reset chargers, unlock connectors - **Authorization**: Local authorization list management and remote ID tag validation - **Firmware Management**: Remote firmware updates and diagnostics file uploads - **Meter Values**: Periodic and transaction-based energy measurement reporting - **Reservation**: Reserve a connector for a specific ID tag OCPP 1.6 core defines 28 unique actions split between charger-initiated and CPMS-initiated operations (with `DataTransfer` going in both directions). The optional Security Whitepaper edition 2 extension adds 11 more — signed firmware, certificate management, log upload, and `SecurityEventNotification` — for a total of about 39 when both are implemented. ### OCPP 2.0.1 OCPP 2.0.1 represents a ground-up rearchitecture of the protocol. Released in 2020, it addresses the most significant gaps in 1.6 while adding support for modern EV charging requirements like [Plug & Charge (ISO 15118)](/blog/iso-15118-plug-and-charge) and vehicle-to-grid (V2G). Key improvements over 1.6: - **Device Model**: A comprehensive, standardized data model for charger configuration --- replacing the ad-hoc key-value approach in 1.6 with a structured component/variable hierarchy - **ISO 15118 Support**: Native support for certificate-based vehicle authentication, enabling true Plug & Charge without RFID cards - **Security Profiles**: Three defined security levels with mandatory TLS, signed firmware updates, and secure boot chains - **Transaction Handling**: Redesigned transaction event model that eliminates the "hanging transaction" problem in 1.6 where a `StopTransaction` message lost in transit could leave a transaction open indefinitely - **Display Messages**: Remote control of charger screen content for pricing information, instructions, or advertisements - **Cost and Tariff**: Real-time cost updates sent to the charger during a transaction - **Improved Smart Charging**: Composite charging schedules, external power limits, and better integration with energy management systems OCPP 2.0.1 defines many more messages than 1.6, organized into 16 functional blocks spanning provisioning, security, transactions, smart charging, and ISO 15118. ## OCPP 1.6 vs 2.0.1: What's the Difference? | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|----------|------------| | **Transport** | WebSocket/JSON or SOAP/XML | WebSocket/JSON only | | **Security** | Optional TLS in core; Profiles 0–3 via Security Whitepaper edition 2 (opt-in) | Mandatory security profiles (1/2/3) | | **ISO 15118** | No native support (hacky `DataTransfer` workarounds) | Full native support for Plug & Charge | | **Smart Charging** | Single `ChargingProfile` stack per connector | Composite schedules, EVSE-level and station-level profiles | | **Device Management** | `GetConfiguration`/`ChangeConfiguration` with flat key-value pairs | Structured Device Model with Components and Variables | | **Transaction Model** | `StartTransaction` + `StopTransaction` (paired messages) | `TransactionEvent` (single message type with Started/Updated/Ended) | | **Message Format** | JSON arrays `[2, id, action, payload]` | Same JSON array format, backward-compatible framing | | **Message Count** | 28 core actions (39 with Security Whitepaper edition 2) | Many more, across 16 functional blocks | | **Firmware Update** | Basic via `UpdateFirmware`; `SignedUpdateFirmware` available via Security Whitepaper edition 2 | Signed firmware with certificate validation | | **Display Messages** | Not supported | `SetDisplayMessage`, `GetDisplayMessages`, `ClearDisplayMessage` | | **Cost Information** | Not supported | Running cost and final cost sent to charger | | **Reservation** | Reserve single connector | Reserve EVSE with connector type preference | | **Connector Model** | Flat: ChargePoint has Connectors | Hierarchical: Station > EVSE > Connector | | **Logging** | `GetDiagnostics` in core; `GetLog` / `LogStatusNotification` via Security Whitepaper edition 2 | `GetLog` with structured log types (diagnostics, security) | | **Certificate Management** | Not in core; full cert lifecycle (`InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds`) available via Security Whitepaper edition 2 | Full certificate lifecycle management | | **Local Auth List** | Basic ID tag list | Extended with ID token types and grouping | | **Error Handling** | Limited; lost `StopTransaction` causes orphan transactions | Sequence numbers and event-based model prevent data loss | ## OCPP Message Types: Complete Reference ### OCPP 1.6 Messages **Charger-initiated (Charge Point to CPMS):** | Message | Purpose | |---------|---------| | `Authorize` | Validate an RFID tag or other credential before allowing charging | | `BootNotification` | Register with the CPMS on startup, report vendor/model/firmware | | `DataTransfer` | Vendor-specific data exchange (escape hatch for custom features) | | `DiagnosticsStatusNotification` | Report status of a diagnostics upload | | `FirmwareStatusNotification` | Report status of a firmware update | | `Heartbeat` | Periodic keep-alive; CPMS responds with current time for clock sync | | `MeterValues` | Report energy consumption, power, voltage, current, temperature, SoC | | `StartTransaction` | Notify CPMS that a charging session has started | | `StatusNotification` | Report connector status changes (OCPP 1.6: Available, Charging, Faulted, and related 1.6 states) | | `StopTransaction` | Notify CPMS that a charging session has ended, include final meter value | **CPMS-initiated (CPMS to Charge Point):** | Message | Purpose | |---------|---------| | `CancelReservation` | Cancel a previously made reservation | | `ChangeAvailability` | Set a connector to operative or inoperative | | `ChangeConfiguration` | Modify a configuration key on the charger | | `ClearCache` | Clear the charger's local authorization cache | | `ClearChargingProfile` | Remove one or more charging profiles | | `DataTransfer` | Vendor-specific data exchange | | `GetCompositeSchedule` | Retrieve the combined effective charging schedule | | `GetConfiguration` | Read configuration key values from the charger | | `GetDiagnostics` | Request the charger to upload diagnostics logs | | `GetLocalListVersion` | Check version number of the local authorization list | | `RemoteStartTransaction` | Remotely start a charging session | | `RemoteStopTransaction` | Remotely stop a charging session | | `ReserveNow` | Reserve a connector for a specific ID tag | | `Reset` | Soft or hard reset the charger | | `SendLocalList` | Update or replace the local authorization list | | `SetChargingProfile` | Install a charging profile for load management | | `TriggerMessage` | Request the charger to send a specific message (e.g., StatusNotification) | | `UnlockConnector` | Remotely unlock the charging cable connector | | `UpdateFirmware` | Instruct the charger to download and install new firmware | ### OCPP 2.0.1 Messages (Selected Key Additions) OCPP 2.0.1 retains the concepts from 1.6 but reorganizes and extends them significantly. Notable new or redesigned messages include: | Message | Purpose | |---------|---------| | `TransactionEvent` | Replaces `StartTransaction`/`StopTransaction` with a unified event model | | `SetVariables` / `GetVariables` | Replace `ChangeConfiguration`/`GetConfiguration` with structured device model access | | `GetBaseReport` | Request a full dump of the charger's device model | | `NotifyReport` | Charger sends device model data in response to `GetBaseReport` | | `RequestStartTransaction` / `RequestStopTransaction` | Renamed remote start/stop with enhanced parameters | | `SetDisplayMessage` | Display custom messages on the charger screen | | `CostUpdated` | Send running cost information during a transaction | | `SetChargingProfile` | Enhanced with composite schedule support and EVSE-level targeting | | `GetCompositeSchedule` | Returns the effective composite from all stacked profiles | | `SetNetworkProfile` | Configure charger network settings remotely | | `InstallCertificate` / `DeleteCertificate` / `GetInstalledCertificateIds` | Full certificate lifecycle management | | `SignCertificate` | Charger requests a new certificate from the CPMS | | `Get15118EVCertificate` | ISO 15118 certificate provisioning for Plug & Charge | | `NotifyEVChargingNeeds` | Vehicle communicates its charging requirements via ISO 15118 | | `ClearedChargingLimit` | External charging limit has been removed | | `NotifyChargingLimit` | Report external limits imposed by energy management | | `ReportChargingProfiles` | Charger reports all installed charging profiles | | `CustomerInformation` | Retrieve or clear customer-related data stored on the charger | | `LogStatusNotification` | Report status of a log upload operation | | `SecurityEventNotification` | Report security-related events (tamper detection, auth failures) | ## What Are the OCPP Security Profiles? OCPP 2.0.1 defines three security profiles that provide escalating levels of protection. Security was one of the weakest areas in OCPP 1.6, where TLS was optional and most deployments ran unencrypted WebSocket connections. ### Security Profile 1: Basic Authentication Security Profile 1 uses unsecured transport (ws://) with HTTP Basic Authentication. The charger sends a username (typically the charge point identity) and password in the WebSocket handshake headers. - **Transport**: Unencrypted WebSocket (`ws://`) - **Authentication**: HTTP Basic Auth (password in Authorization header) - **Use case**: Lab environments, isolated private networks - **Risk**: Credentials and all OCPP messages travel in plaintext; vulnerable to interception This profile exists primarily for backward compatibility and testing. It should never be used in production deployments over public networks. ### Security Profile 2: TLS with Basic Authentication Security Profile 2 adds TLS encryption while retaining password-based authentication. The charger validates the CPMS server certificate against a trusted root, ensuring it connects to the legitimate backend. - **Transport**: Encrypted WebSocket (`wss://`) with server-side TLS - **Authentication**: HTTP Basic Auth over TLS - **Certificate**: Charger validates CPMS server certificate - **Use case**: Production deployments where client certificate management is not feasible - **Advantage**: All traffic is encrypted; CPMS identity is verified ### Security Profile 3: TLS with Client-Side Certificates Security Profile 3 provides mutual TLS (mTLS) authentication. Both the charger and the CPMS present and validate X.509 certificates, providing the strongest available authentication. - **Transport**: Encrypted WebSocket (`wss://`) with mutual TLS - **Authentication**: Client certificate (charger) + server certificate (CPMS) - **Certificate management**: Requires PKI infrastructure for provisioning, rotating, and revoking charger certificates - **Use case**: High-security deployments, public charging infrastructure, compliance-driven environments - **Advantage**: Eliminates password-based vulnerabilities; cryptographic identity verification for both endpoints Additionally, OCPP 2.0.1 mandates signed firmware updates. The charger validates the cryptographic signature of firmware binaries before installation, preventing malicious firmware injection --- a critical concern for internet-connected devices on public infrastructure. ## How Does Smart Charging Work with OCPP? [Smart charging](/blog/smart-charging-explained) is one of OCPP's most important features. It enables dynamic power management across a charging site, balancing grid constraints, energy costs, renewable availability, and vehicle needs. ### How SetChargingProfile Works A charging profile defines a power or current limit over time. The CPMS sends a `SetChargingProfile` message to the charger containing: - **Stack level**: Priority of this profile (higher levels override lower ones) - **Charging profile purpose (OCPP 1.6)**: `ChargePointMaxProfile` (charge-point limit), `TxDefaultProfile` (default for new transactions), or `TxProfile` (specific to an active transaction) - **Charging profile purpose (OCPP 2.0.1)**: `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, `TxDefaultProfile`, or `TxProfile` — there is no `ChargePointMaxProfile` in 2.0.1 - **Charging schedule**: A time-based series of power or current limits Example: A site with 150 kW of available grid capacity and 4 DC fast chargers can use an OCPP 1.6 `ChargePointMaxProfile` (or an OCPP 2.0.1 `ChargingStationMaxProfile`) to distribute power dynamically. When one charger is idle, the others can draw more. When all four are active, each gets 37.5 kW. When grid load peaks, the CSMS can reduce the site limit to 100 kW, and the charger recalculates the composite schedule. In OCPP 1.6, charging profiles operate at the connector level with a simple stack. In OCPP 2.0.1, the system is significantly more capable: - **EVSE-level and station-level profiles**: Apply limits at different points in the hierarchy - **Composite schedule calculation**: The charger computes the effective limit from all active profiles, and the CPMS can query this composite via `GetCompositeSchedule` - **External limits**: The charger can report constraints from an external energy management system via `NotifyChargingLimit` - **Absolute and relative schedules**: Profiles can be tied to absolute timestamps or relative to transaction start Smart charging is essential for fleet depot charging, workplace charging, and residential multi-unit installations where grid capacity is shared. ## Who Uses OCPP? OCPP adoption spans the entire EV charging value chain. ### Charge Point Operators (CPOs) CPOs deploy and manage physical charging infrastructure. Major CPOs running OCPP-connected networks include: - **ChargePoint** (North America, Europe) --- operates one of the largest OCPP-connected networks globally - **Fastned** (Europe) --- high-power fast charging along highways - **EVgo** (United States) --- one of the largest public fast-charging networks in the U.S. - **Allego** (Europe) --- pan-European charging network - **Shell Recharge / Ubitricity** (Global) --- leveraging OCPP to unify charger management across acquired brands - **bp pulse** (Europe, North America) --- rapidly expanding OCPP-connected infrastructure ### CPMS Vendors Software companies building charging station management systems that communicate with chargers via OCPP: - **Driivz** (acquired by Vontier) - **EVConnect** - **AMPECO** - **Current** - **EV.energy** - **Open Charge Point (open-source)** ### Charger Manufacturers Hardware manufacturers shipping OCPP-compliant chargers: - **ABB E-mobility** --- DC fast chargers (Terra series) - **Schneider Electric** --- AC and DC chargers for commercial deployments - **EVBox** --- residential and commercial AC chargers - **Wallbox** --- residential and small commercial chargers - **Alfen** --- smart AC chargers popular in the Netherlands - **Tritium** --- high-power DC fast chargers - **Kempower** --- modular DC fast charging systems - **Autel Energy** --- AC and DC chargers for North American market - **BTC Power** --- DC fast chargers for fleet and public deployments ### Energy Companies and Utilities Utilities integrating EV charging into grid management strategies use OCPP's smart charging capabilities to implement demand response, time-of-use optimization, and vehicle-to-grid (V2G) programs. Companies like Enel X, E.ON, and Engie are active participants in the OCPP ecosystem. ## OCPP vs OCPI vs OICP: How Do They Compare? OCPP is one of several open protocols in the EV charging ecosystem. Each serves a different purpose. | Protocol | Full Name | Purpose | Communication Path | |----------|-----------|---------|-------------------| | **OCPP** | Open Charge Point Protocol | Charger-to-backend communication | Charge Point <-> CPMS | | **OCPI** | Open Charge Point Interface | Roaming and interoperability between networks | CPMS <-> CPMS (or CPMS <-> eMSP) | | **OICP** | Open InterCharge Protocol | Roaming (primarily Hubject ecosystem) | CPMS <-> Hubject Hub <-> CPMS | | **ISO 15118** | Vehicle-to-grid communication | Vehicle-to-charger communication | EV <-> Charge Point | | **OpenADR** | Open Automated Demand Response | Grid demand response signals | Utility <-> Energy Management System | **OCPP** operates between the charger and the backend. It handles "make the charger do things" --- start charging, report meter values, update firmware. **[OCPI](/blog/what-is-ocpi)** operates between charging networks. It handles "let an eMSP customer use a CPO's charger" --- roaming, real-time location data, tariff information, and CDR (Charge Detail Record) exchange. If OCPP is the protocol inside a network, OCPI is the protocol between networks. **OICP** serves a similar roaming purpose to OCPI but uses a centralized hub model (Hubject) rather than peer-to-peer connections. It is dominant in Germany and parts of Central Europe. **ISO 15118** operates between the vehicle and the charger (below OCPP in the stack). It enables Plug & Charge authentication and communicates the vehicle's charging requirements. OCPP 2.0.1 has specific messages to relay ISO 15118 data between the charger and CPMS. ## How Do You Test OCPP Implementations? Testing OCPP is inherently complex. The specification defines hundreds of message flows, error scenarios, and state transitions that must work correctly across different network conditions. For a comprehensive testing approach, see our [OCPP testing guide](/blog/ocpp-testing-guide) and [EV charger testing guide](/blog/ev-charger-testing-guide). ### Challenges of Physical Testing Testing with real hardware is slow and expensive: - A single networked DC fast charger is a major capital purchase, and grid upgrades, trenching, and permitting push the installed cost far higher - Testing requires physical EV connectors, power supplies, and often actual vehicles - Reproducing edge cases (network drops mid-transaction, firmware corruption, concurrent sessions) is difficult with physical equipment - Test cycles with hardware typically take weeks to months ### Simulation-Based Testing **OCPPLab** provides cloud-based OCPP simulation that eliminates these constraints: - **Scale**: Deploy 1,000+ virtual charge points in minutes, simulating an entire charging network - **Protocol coverage**: Test both OCPP 1.6 and 2.0.1 with full message type support - **Realistic behavior**: Simulate real charger behaviors from 100+ device models, including vendor-specific quirks and timing characteristics - **Edge case testing**: Simulate network failures, malformed messages, slow responses, concurrent operations, and protocol error conditions that are nearly impossible to reproduce with hardware - **CI/CD integration**: Automate regression testing as part of your development pipeline - **Smart charging validation**: Test complex charging profile scenarios, composite schedule calculations, and load management algorithms Teams using OCPPLab typically compress OCPP QA cycles from months to weeks and sharply reduce testing infrastructure costs. ## OCPP Certification and Compliance The Open Charge Alliance operates an OCPP certification program that validates conformance to the specification. Certification involves: 1. **Self-testing**: Vendors run the OCA's test tool against their implementation 2. **Conformance testing**: An accredited test lab executes the official test suite 3. **Interoperability testing**: The implementation is tested against other certified products Certified products are listed in the OCA's product directory. While certification is not legally required in most jurisdictions, many RFPs and government funding programs require or strongly prefer OCA-certified products. The EU's Alternative Fuels Infrastructure Regulation (AFIR) references OCPP as the communication standard for publicly accessible charging points. ## Frequently Asked Questions ### Is OCPP free to use? Yes. OCPP is an open protocol published by the Open Charge Alliance under royalty-free terms. Anyone can download the specification and implement it without licensing fees. The specification documents are freely available on the OCA website. Certification is optional and involves a fee, but implementing the protocol itself costs nothing. ### What is the difference between OCPP and OCPI? OCPP handles communication between a charger and its management backend (CPMS) --- operations like starting charging sessions, reporting energy usage, and updating firmware. OCPI handles communication between different charging networks for roaming, allowing an EV driver subscribed to one network to use chargers on another. OCPP operates inside a network; OCPI operates between networks. ### Do all EV chargers support OCPP? Most commercial EV chargers sold today support OCPP 1.6 at minimum. Tesla Superchargers historically used a proprietary protocol, but Tesla has begun adopting OCPP for its chargers that serve non-Tesla vehicles as part of NEVI-funded deployments. Some low-cost residential chargers may lack OCPP support since they are designed for standalone operation without backend management. ### What is a CSMS? What about CPMS? A **CSMS** (Charging Station Management System) is the OCPP 2.0.1 name for the backend that manages chargers over OCPP. OCPP 1.6 calls the same role **Central System**. **CPMS** (Charge Point Management System) is industry slang for that backend — it is not the 2.0.1 spec acronym, and it does not expand to Charging Station Management System. The backend handles authorization, sessions, billing, energy monitoring, remote operations, firmware updates, and analytics. ### Which OCPP version should I implement? If you are starting a new implementation in 2026, support both OCPP 1.6 and 2.0.1. Most chargers in the field still run 1.6, so your CSMS needs 1.6 for backward compatibility. New charger models increasingly ship 2.0.1, and features like ISO 15118 Plug & Charge, mandatory security profiles, and the device model require 2.0.1. OCPP 2.1 is a published spec (2025); OCPPLab does not implement it. The 1.6 and 2.0.1 versions differ substantially in security, device modeling, and transaction handling. ### How does OCPP handle offline charging? OCPP supports offline operation through the Local Authorization List. The CPMS pushes a list of authorized ID tags to the charger via `SendLocalList`. When the charger loses its WebSocket connection, it can still authorize users against this local list and start charging sessions. Transaction data (meter values, start/stop events) is queued locally and transmitted to the CPMS when connectivity is restored. OCPP 2.0.1 improves this with its event-based transaction model, which handles message loss more gracefully than 1.6's paired start/stop messages. ### Is OCPP secure? Core OCPP 1.6 has minimal built-in security --- TLS is optional, and many deployments run unencrypted. The optional **OCPP 1.6 Security Whitepaper edition 2** retroactively adds security profiles (0/1/2/3), certificate management, signed firmware updates, and `SecurityEventNotification` to 1.6, but it is opt-in per deployment, so a large portion of the installed base still runs without it. OCPP 2.0.1 makes the same profile model mandatory (renumbered Profile 1/2/3) and bakes signed firmware and security event logging into the core spec. For production deployments, Security Profile 2 (TLS with basic auth) is the practical minimum, and Security Profile 3 (mutual TLS) is recommended for public infrastructure. ### What is the OCPP heartbeat? The `Heartbeat` message is a lightweight keep-alive sent by the charger to the CPMS at a regular interval (configured in the `BootNotification` response, typically 30--300 seconds). It serves two purposes: confirming that the charger is online and connected, and synchronizing the charger's internal clock with the CPMS server time (the `Heartbeat` response includes the current UTC timestamp). If the CPMS stops receiving heartbeats, it marks the charger as offline. ### Can OCPP support vehicle-to-grid (V2G)? OCPP 2.0.1 includes foundational ISO 15118 integration (`NotifyEVChargingNeeds`, charging profiles that can carry negative power). **OCPP 2.1** (published 2025) is the OCA spec aimed at ISO 15118-20 bidirectional / V2G workflows. OCPPLab implements 1.6 and 2.0.1 only — it does not negotiate `ocpp2.1`. Full V2G orchestration typically also needs grid-side protocols such as OpenADR. ### What happens when OCPP messages fail? When a message fails (timeout, network error, or `CallError` response), the behavior depends on the message type. Critical messages like `StartTransaction` and `StopTransaction` in OCPP 1.6 are queued and retried until delivered. In OCPP 2.0.1, the `TransactionEvent` message carries a per-transaction `seqNo` and the Charging Station replays queued offline events in order on reconnect, so the CPMS can detect gaps and reconstruct the full transaction without losing data. (OCPP 2.0.1 does not define an explicit retransmission request — gap recovery relies on the Charging Station's offline message queue.) For a complete guide to error handling, see our [OCPP error codes reference](/blog/ocpp-error-codes-reference). --- ## What Is OCPI? EV Charging Roaming Protocol Explained Source: https://ocpplab.com/blog/what-is-ocpi What OCPI is, how EV charging roaming works, and what CPOs and eMSPs must know about OCPI 2.1.1 vs 2.2.1, all 8 modules, hubs, and how to implement it. **Quick answer:** OCPI (Open Charge Point Interface) is an open REST/HTTPS protocol from the [EVRoaming Foundation](https://evroaming.org/) used between EV charging back-office systems — typically a CPO (Charge Point Operator) and an eMSP (e-Mobility Service Provider) — to enable roaming. The two production versions are **OCPI 2.1.1** (the broad interoperability baseline, alpha-3 country codes, no Hub role) and **OCPI 2.2.1** (adds Hub/NSP/NAP/SCSP roles, ChargingProfiles and HubClientInfo modules, alpha-2 country codes + party_id). OCPI (Open Charge Point Interface) is the protocol that enables EV charging roaming between backend systems such as CPO and eMSP platforms. Developed and maintained by the [EVRoaming Foundation](https://evroaming.org/), OCPI standardizes how networks exchange locations, sessions, tariffs, tokens, and billing records so drivers can charge outside their home network. The current specifications and reference implementations are hosted on [GitHub at ocpi/ocpi](https://github.com/ocpi/ocpi). If you are implementing or validating a roaming stack, continue with [OCPI 2.1.1 testing](/protocols/ocpi-2-1-1) and [OCPI 2.2.1 testing](/protocols/ocpi-2-2-1) for version-specific coverage. If you are deciding which version to implement, read the full [OCPI 2.1.1 vs 2.2.1 comparison](/blog/ocpi-2-1-1-vs-2-2-1). If you are preparing for partner onboarding or hub validation, see [OCPI roaming testing](/use-cases/ocpi-roaming-testing) or [book an OCPI demo](/contact). ## Why Does OCPI Exist? The EV Charging Roaming Problem Without a roaming protocol, every EV charging network operates as a walled garden. A driver subscribed to Network A cannot use Network B's chargers without creating a separate account, downloading another app, and managing another payment method. This fragmentation is the single largest friction point for EV adoption today. OCPI solves this by standardizing how charging networks exchange data. The result is an experience similar to mobile phone roaming: one subscription, universal access. Here is what OCPI enables in practice: - **Driver convenience**: A single app or RFID card works across all participating networks, eliminating the need for dozens of accounts - **Network growth**: [CPOs](/blog/cpo-vs-emsp-explained) gain access to a larger customer base without incremental marketing spend - **Automated settlement**: Billing, invoicing, and revenue sharing between networks happen programmatically through standardized Charge Detail Records - **Market expansion**: [eMSPs](/blog/cpo-vs-emsp-explained) can offer nationwide or continent-wide coverage without owning or operating a single charger - **Regulatory compliance**: The EU Alternative Fuels Infrastructure Regulation (AFIR) requires ad-hoc access to all public chargers, which in practice demands roaming capability As of February 2026, [GIREVE's monthly *Roaming in Europe* barometer](https://www.gireve.com/roaming-in-europe-february-2026/) reported roughly **695,000 charge points** connected to its OCPI-mediated platform across dozens of European countries, making it the largest roaming hub on the continent. [Hubject's intercharge network](https://www.hubject.com/) — which carries both OCPI and OICP traffic — reports connecting **over 1,000,000 charge points across 70+ countries on four continents**. These figures reflect the protocol's central role in EV roaming today. The OCPI 2.2.1 specification itself defines **8 modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands, ChargingProfiles, HubClientInfo) on top of Credentials + Versions — published openly by the [EVRoaming Foundation](https://evroaming.org/). ## How Does OCPI Work? Architecture and Technical Design OCPI is a REST API protocol built on standard HTTP. Two parties -- typically a [CPO (Charge Point Operator) and an eMSP (e-Mobility Service Provider)](/blog/cpo-vs-emsp-explained) -- establish a peer-to-peer connection and exchange structured JSON data over HTTPS. Unlike [OCPP](/blog/what-is-ocpp), which uses persistent WebSocket connections between chargers and backends, OCPI uses stateless HTTP requests between backend systems. ### The OCPI Credential Handshake Before any data exchange occurs, both parties must complete a credential handshake. This is a mutual authentication process: 1. **Registration**: Party A sends a `POST /credentials` request to Party B, including its `TOKEN_A` (a pre-shared token exchanged out-of-band) and a list of supported OCPI versions 2. **Version negotiation**: Both parties agree on the highest mutually supported OCPI version 3. **Endpoint discovery**: Each party retrieves the other's module endpoints via `GET /versions/{version_number}` 4. **Token exchange**: Party B responds with `TOKEN_B`. From this point, Party A uses `TOKEN_B` to authenticate requests to Party B, and vice versa 5. **Connection active**: Both parties can now exchange data through the agreed-upon module endpoints This handshake ensures that credentials are never static. Either party can re-register at any time to rotate tokens, which is a significant security advantage over protocols that rely on fixed API keys. ### Push and Pull Communication Modes OCPI supports two data synchronization modes, and most production deployments use both: **Pull mode** (Client-Owned): The receiving party periodically requests data from the sender using standard `GET` requests with pagination. For example, an eMSP pulls location data from a CPO by calling `GET /locations?date_from=2025-01-01T00:00:00Z&offset=0&limit=50`. This is simple to implement but introduces latency between updates. **Push mode** (Server-Owned): The sending party proactively pushes updates to the receiver using `PUT`, `PATCH`, or `DELETE` requests. When a CPO updates a charger's status, it immediately sends a `PATCH /locations/{location_id}/{evse_id}` to the eMSP. This provides near-real-time data but requires the receiver to expose endpoints that accept incoming requests. In practice, most implementations use pull mode for initial data synchronization (fetching the full dataset) and push mode for incremental updates (real-time status changes, new sessions, etc.). ### OCPI Versioning and Endpoint Discovery Every OCPI implementation exposes a versions endpoint that lists all supported protocol versions: ``` GET /ocpi/versions ``` This returns a list of version objects, each containing a version number and URL. The connecting party then queries the specific version URL to discover available module endpoints. This design means a single OCPI server can support multiple protocol versions simultaneously, enabling gradual migration without breaking existing connections. ## All OCPI Modules Explained OCPI is organized into modules, each handling a specific domain of the roaming workflow. A party does not need to implement every module -- only those relevant to its role and business needs. ### Locations Module The Locations module is the foundation of OCPI. It describes where chargers are, what capabilities they have, and whether they are currently available. A Location object contains one or more EVSEs (Electric Vehicle Supply Equipment), each with one or more Connectors. **Data hierarchy**: Location > EVSE > Connector **Key fields**: address, coordinates, operator info, opening hours, EVSE status (`AVAILABLE`, `BLOCKED`, `CHARGING`, `INOPERATIVE`, `OUTOFORDER`, `PLANNED`, `REMOVED`, `RESERVED`, `UNKNOWN`), connector type (Type 2, CCS2, CHAdeMO), power output, and pricing. **Example use case**: An eMSP pulls all locations from a CPO to populate its driver-facing app with a map of available chargers. When an EVSE status changes from AVAILABLE to CHARGING, the CPO pushes the update so the app reflects real-time availability. ### Sessions Module The Sessions module provides real-time data about active charging sessions. While a session is in progress, both parties can track energy delivered, current power, cost accrued, and session state. **Key fields**: session ID, start timestamp, kWh delivered, [CDR](/blog/what-is-csms) token (identifying the driver), status (ACTIVE, COMPLETED, INVALID, PENDING), and total cost. **Example use case**: An eMSP displays a live charging dashboard in its app showing the driver how much energy has been delivered, current charging speed, and estimated cost so far. ### CDRs Module (Charge Detail Records) CDRs are the billing backbone of OCPI. A CDR is generated after a session completes and contains all information needed for invoicing and settlement between the CPO and eMSP. **Key fields**: start/stop timestamps, total energy (kWh), total time, total parking time, total cost, tariff applied, charging periods (time-based breakdown of the session), and the authorization token used. **Example use case**: After a driver finishes charging, the CPO generates a CDR and pushes it to the eMSP. The eMSP uses this CDR to invoice the driver and reconcile payments with the CPO at the end of the billing cycle. ### Tariffs Module The Tariffs module defines pricing structures that CPOs apply to their charge points. OCPI tariffs support complex pricing models including time-of-use rates, energy-based pricing, flat fees, parking fees, and combinations thereof. **Key fields**: tariff ID, currency, tariff elements (each containing price components and restrictions like time-of-day, min/max kWh, day of week), and tariff type (`AD_HOC_PAYMENT`, `PROFILE_CHEAP`, `PROFILE_FAST`, `PROFILE_GREEN`, `REGULAR` — added in 2.2.1; not present in 2.1.1). **Example use case**: A CPO publishes a tariff that charges 0.35 EUR/kWh during peak hours (08:00-20:00) and 0.25 EUR/kWh during off-peak hours, plus a 0.05 EUR/min idle fee after the session completes. The eMSP displays this pricing to the driver before they start charging. ### Tokens Module The Tokens module handles driver authorization. An eMSP pushes its driver tokens (RFID UIDs, app-based virtual tokens, or vehicle-based tokens) to the CPO so the CPO can authorize charging sessions locally without a real-time callback. **Key fields**: token UID, token type (`RFID`, `OTHER` in 2.1.1; `RFID`, `APP_USER`, `AD_HOC_USER`, `OTHER` in 2.2.1), contract ID, issuer, valid flag, and whitelist type (`ALWAYS`, `ALLOWED`, `ALLOWED_OFFLINE`, `NEVER`). **Example use case**: An eMSP pushes all its active driver tokens to a CPO. When a driver taps their RFID card at the CPO's charger, the CPO can authorize the session instantly by checking its local token cache, even if the network connection to the eMSP is temporarily unavailable. ### Commands Module The Commands module enables remote control of charging sessions. An eMSP can send commands to a CPO to start or stop a session, reserve a charger, or unlock a connector on behalf of a driver. **Supported commands**: - `START_SESSION`: Remotely start a charging session at a specific EVSE - `STOP_SESSION`: Remotely stop an active session - `RESERVE_NOW`: Reserve an EVSE for a specific driver for a limited time - `UNLOCK_CONNECTOR`: Remotely unlock a connector (useful if the cable is stuck) **Example use case**: A driver opens their eMSP app, selects a charger on the map, and taps "Start Charging." The eMSP sends a `START_SESSION` command to the CPO via OCPI, and the CPO relays it to the charger via [OCPP](/blog/what-is-ocpp). ### ChargingProfiles Module Added in OCPI 2.2, the ChargingProfiles module allows an eMSP to set power limits or charging schedules on behalf of the driver. This is essential for smart charging and demand response scenarios. **Key fields**: charging profile (containing schedule periods with power limits), response URL (for async result notification). **Example use case**: A driver tells their eMSP app they need 80% charge by 7 AM and want the cheapest rate. The eMSP calculates an optimal charging schedule and sends a ChargingProfile to the CPO, which applies it to the charger via [OCPP charging profiles](/blog/ocpp-1-6-vs-2-0-1). The charger modulates power delivery according to the schedule. ### HubClientInfo Module The HubClientInfo module is specific to hub-based deployments. It allows a roaming hub (like [GIREVE](/blog/gireve-hub-integration)) to inform connected parties about all other parties connected to the hub, including their roles and connection status. **Key fields**: party ID, country code, role (CPO, eMSP, HUB), status (CONNECTED, OFFLINE, PLANNED, SUSPENDED). **Example use case**: An eMSP connected to GIREVE receives HubClientInfo updates listing all CPOs currently connected to the hub. The eMSP uses this to know which CPO networks are available for its drivers and can display coverage accordingly. ## OCPI 2.1.1 vs 2.2.1: What Changed? OCPI has gone through several iterations. The two versions you will encounter in production today are 2.1.1 and 2.2.1. Understanding the differences is critical for implementation planning. ### OCPI 2.1.1 Released in 2019, OCPI 2.1.1 is the most widely deployed version. It covers all core roaming functionality and remains the baseline requirement for most roaming hub connections. If you are building your first OCPI integration, you will almost certainly start here. ### OCPI 2.2.1 Released in 2021, OCPI 2.2.1 is a significant upgrade that adds hub support, smart charging, and improved tariff handling. Adoption is growing rapidly as roaming hubs and larger operators migrate. ### Detailed Version Comparison | Feature | OCPI 2.1.1 | OCPI 2.2.1 | |---------|-----------|-----------| | **Core modules** (Locations, Sessions, CDRs, Tariffs, Tokens, Commands) | Yes | Yes | | **Hub role support** | No -- peer-to-peer only | Yes -- native hub/platform role | | **HubClientInfo module** | Not available | Full support | | **ChargingProfiles module** | Not available | Full support for smart charging | | **Tariff types** | Basic tariff model (no `type` field) | Extended with `tariff_type` enum (`AD_HOC_PAYMENT`, `PROFILE_CHEAP`, `PROFILE_FAST`, `PROFILE_GREEN`, `REGULAR`) | | **Tariff alt_text / alt_url** | Not available | Human-readable tariff descriptions and external links | | **Token types** | RFID, OTHER | RFID, APP_USER, AD_HOC_USER, OTHER | | **Authorization reference** | Basic | Enhanced with authorization_reference for linking tokens to sessions | | **Async commands** | Async via `response_url` callback (same pattern as 2.2.1) | Async via `response_url` callback | | **Connector-level pricing** | Limited | Full connector-level tariff assignment | | **Energy mix info** | Basic | Detailed energy source breakdown per location | | **Calibration law support** | `signed_data` field on CDR for signed metering | `signed_data` field on CDR; richer signed-data context fields added | | **Error handling** | Standardized OCPI status codes (1xxx success, 2xxx client, 3xxx server) | Same plus 4xxx Hub error class | | **Pagination** | Supported | Enhanced with X-Total-Count and X-Limit headers | **Recommendation**: Implement OCPI 2.2.1 if you are connecting through a roaming hub, need smart charging capabilities, or operate in Germany (Eichrecht compliance). Start with 2.1.1 if you need the fastest path to production for basic roaming. ## OCPI vs OCPP: What Is the Difference? This is the most common question in EV charging protocol discussions. The short answer: [OCPP (Open Charge Point Protocol)](/blog/what-is-ocpp) manages communication between a charger and its [backend system (CPMS)](/blog/what-is-csms). OCPI manages communication between backend systems of different charging networks. They operate at different layers of the stack and are complementary, not competing. | Dimension | OCPP | OCPI | |-----------|------|------| | **Full name** | Open Charge Point Protocol | Open Charge Point Interface | | **Purpose** | Charger-to-backend communication | Backend-to-backend roaming | | **Parties involved** | Charge Point and [CPMS](/blog/what-is-csms) | CPO backend and eMSP backend | | **Transport protocol** | WebSocket (persistent connection) | REST API over HTTPS (stateless) | | **Data format** | JSON (OCPP 1.6) or SOAP (OCPP 1.6S) | JSON | | **Connection type** | Persistent, bidirectional | Request/response, stateless | | **Scope** | Single-network charger management | Cross-network interoperability | | **Maintained by** | Open Charge Alliance (OCA) | EVRoaming Foundation | | **Current versions** | [1.6, 2.0.1](/blog/ocpp-1-6-vs-2-0-1) | 2.1.1, 2.2.1 | | **Typical data exchanged** | Boot notifications, heartbeats, meter values, firmware updates | Locations, sessions, CDRs, tariffs, tokens | | **Example message** | "Start transaction on connector 1" | "Driver X from eMSP Y is authorized to charge on your network" | | **Security** | TLS + basic auth or certificate-based | TLS + TOKEN-based authentication via credential handshake | **How they work together**: When a roaming driver starts a session, the eMSP sends an OCPI command to the CPO's backend. The CPO's backend then sends an OCPP RemoteStartTransaction message to the physical charger. Session data flows back up through OCPP (MeterValues, StopTransaction) and is then shared with the eMSP via OCPI (Sessions, CDRs). ## OCPI vs OICP vs OCHP: EV Charging Roaming Protocols Compared OCPI is not the only roaming protocol in the EV charging industry. Two other protocols serve similar purposes: OICP (Open InterCharge Protocol) and OCHP (Open Clearing House Protocol). Understanding the differences helps when choosing which ecosystem to join. | Dimension | OCPI | OICP | OCHP | |-----------|------|------|------| | **Maintained by** | EVRoaming Foundation | Hubject | e-clearing.net (Smartlab) | | **Governance** | Open community | Proprietary (single vendor) | Open community | | **License** | Creative Commons | Proprietary | Creative Commons | | **Primary hub** | GIREVE, multiple hubs | Hubject (intercharge) | e-clearing.net | | **Geographic focus** | Europe-wide, expanding globally | Europe, strong in DACH region | Central Europe | | **Transport** | REST API (JSON) | REST API (JSON) | SOAP/XML (legacy) and REST | | **Peer-to-peer support** | Yes -- native | Limited -- hub-centric | Limited -- hub-centric | | **Smart charging** | Yes (2.2.1) | Yes | Limited | | **Plug&Charge (ISO 15118)** | Partial support | Full support via Hubject PKI | Not supported | | **Adoption** | Broad, multi-vendor | Large Hubject-centric base | Niche, Central Europe | | **Open specification** | Freely available on GitHub | Available under NDA | Freely available | **OCPI** has the broadest adoption and the most open governance model. It is the default choice for most new implementations. **OICP** is tightly coupled with Hubject and offers mature Plug&Charge support through Hubject's PKI infrastructure, making it strong in the German-speaking market. **OCHP** is the oldest of the three and is most common among e-clearing.net members, but has seen less adoption growth in recent years. Many large operators implement multiple protocols. A CPO connected to both GIREVE (via OCPI) and Hubject (via OICP) maximizes its roaming reach. ## Roaming Hubs: GIREVE, Hubject, and e-clearing Rather than establishing direct OCPI connections with every partner (which does not scale), most CPOs and eMSPs connect through a roaming hub. A single hub connection gives access to all other parties connected to that hub. ### GIREVE [GIREVE](/blog/gireve-hub-integration) is the largest OCPI-based roaming hub in Europe. Founded in France in 2013, it has grown into the dominant roaming platform on the continent. - **Coverage**: As of February 2026, roughly 695,000 charge points across dozens of European countries ([GIREVE *Roaming in Europe* barometer](https://www.gireve.com/roaming-in-europe-february-2026/)) - **Partners**: Several hundred connected CPOs and eMSPs - **Protocol support**: OCPI 2.1.1 and 2.2.1 (primary), plus eMIP (GIREVE's legacy protocol) - **Key features**: Quality scoring of charge points, B2B marketplace for roaming agreements, data analytics - **Certification**: GIREVE runs a certification process for new OCPI connections, including test scenarios that validate your implementation ### Hubject Hubject operates the intercharge network, the largest global roaming platform by geographic reach. - **Coverage**: As of 2026, over 1,000,000 charge points across 70+ countries on four continents ([Hubject](https://www.hubject.com/)) - **Protocol support**: OICP (primary), OCPI 2.2.1 (growing) - **Key features**: Plug&Charge PKI infrastructure (ISO 15118), eRoaming marketplace, global interoperability - **Market position**: Strongest in Germany, Austria, and Switzerland; expanding aggressively in North America and Asia-Pacific ### e-clearing.net e-clearing.net is a pan-European clearing house originally developed by Smartlab (now part of the Recharge group). - **Coverage**: Primarily Central Europe (Germany, Netherlands, Belgium, Austria) - **Protocol support**: OCHP (primary), OCPI (supported) - **Key features**: Clearing and settlement services, contract management, direct roaming facilitation - **Market position**: Smaller than GIREVE and Hubject but well-established among Central European utilities ## How Do CPOs Use OCPI? A [Charge Point Operator (CPO)](/blog/cpo-vs-emsp-explained) uses OCPI to expose its charging infrastructure to external networks. Here is what a CPO typically implements: **Data provider role** (CPO pushes data to eMSPs): - **Locations**: Publish all charge point locations, EVSE statuses, connector types, and real-time availability - **Sessions**: Share active session data so eMSPs can display live charging information to their drivers - **CDRs**: Generate and push Charge Detail Records after each roaming session for billing and settlement - **Tariffs**: Publish pricing structures so eMSPs can display accurate costs to drivers before they start charging **Data receiver role** (CPO receives data from eMSPs): - **Tokens**: Receive and cache driver authorization tokens for local, offline-capable authorization - **Commands**: Accept remote start/stop, reservation, and unlock commands from eMSP apps **Business impact**: A mid-sized CPO that connects to GIREVE via OCPI can immediately access hundreds of thousands of eMSP subscribers without any direct sales or marketing effort. For public charging operators, roaming sessions can account for a meaningful and growing share of total revenue. ## How Do eMSPs Use OCPI? An [eMSP (e-Mobility Service Provider)](/blog/cpo-vs-emsp-explained) uses OCPI to aggregate charging infrastructure from multiple CPOs and present it to its subscribers. Here is what an eMSP typically implements: **Data receiver role** (eMSP pulls/receives data from CPOs): - **Locations**: Aggregate charge point data from all connected CPOs to build a comprehensive charging map - **Sessions**: Receive real-time session updates to display in the driver app - **CDRs**: Receive billing records to invoice drivers and reconcile with CPOs - **Tariffs**: Receive pricing data to display accurate cost estimates **Data provider role** (eMSP pushes data to CPOs): - **Tokens**: Push driver authorization tokens to all connected CPOs for local authorization - **Commands**: Send remote start/stop and reservation commands on behalf of drivers - **ChargingProfiles**: Send smart charging schedules (OCPI 2.2.1) based on driver preferences **Business impact**: An eMSP connected to one roaming hub can offer its drivers access to hundreds of thousands of charge points across multiple countries without deploying any hardware. The entire value proposition -- "charge anywhere with one app" -- depends on OCPI working reliably. ## How Do You Implement OCPI? A Step-by-Step Guide Implementing OCPI requires building a REST API server and client that conforms to the OCPI specification. Here is a high-level roadmap: ### Step 1: Define Your Role and Scope Determine whether you are implementing as a CPO, eMSP, or both. This determines which modules you need and whether you are primarily a data sender or receiver. ### Step 2: Choose Your OCPI Version For most new implementations, start with OCPI 2.2.1. If your target roaming hub only requires 2.1.1, start there. Support both versions if possible -- OCPI's version discovery mechanism makes this straightforward. ### Step 3: Implement Core Endpoints Build the required endpoints in order of dependency: 1. **Versions and Credentials**: These are mandatory. Without them, no connection can be established. 2. **Locations** (if CPO): This is the most data-intensive module and typically requires the most development effort. 3. **Tokens** (if eMSP): Push your driver tokens to enable authorization. 4. **Sessions and CDRs**: These handle the billing workflow and are required for any commercial roaming. 5. **Tariffs**: Needed for price transparency. 6. **Commands**: Needed for remote start/stop from eMSP apps. ### Step 4: Implement Push and Pull Synchronization Build both pull endpoints (for initial sync and periodic reconciliation) and push endpoints (for real-time updates). Implement proper pagination handling with `offset`, `limit`, and `date_from` parameters. ### Step 5: Connect to a Roaming Hub Contact your target hub ([GIREVE](/blog/gireve-hub-integration), Hubject, or e-clearing) and begin their onboarding process. Each hub has a staging environment for testing. ### Step 6: Test End-to-End Validate the full workflow: credential handshake, location sync, token exchange, remote start, session tracking, CDR generation, and settlement. This is where most implementations encounter issues with edge cases -- malformed data, timeout handling, concurrent updates, and tariff calculation discrepancies. ## How Do You Test OCPI Implementations? Testing OCPI is challenging because it requires simulating both sides of the protocol. You need to act as both a CPO and an eMSP, generate realistic data, and validate complex interactions across multiple modules. Common testing challenges include: - Simulating the credential handshake and token rotation - Generating realistic location data with proper EVSE/Connector hierarchies - Testing push and pull synchronization, including conflict resolution - Validating CDR calculations against published tariffs - Simulating hub-based routing (for OCPI 2.2.1) - Testing error handling and edge cases (network timeouts, invalid tokens, concurrent session updates) **OCPPLab** provides OCPI testing tools alongside its [OCPP emulator](/blog/what-is-ocpp), letting you validate both protocols in a single environment. You can simulate CPO and eMSP endpoints, generate realistic sessions and CDRs, test tariff calculations, validate [GIREVE-compatible](/blog/gireve-hub-integration) hub integration, and run full end-to-end roaming scenarios without needing a live roaming partner. ## Frequently Asked Questions About OCPI ### What does OCPI stand for? OCPI stands for Open Charge Point Interface. It is an open protocol maintained by the EVRoaming Foundation that standardizes data exchange between EV charging networks to enable roaming. The name is often confused with [OCPP (Open Charge Point Protocol)](/blog/what-is-ocpp), but they serve different purposes: OCPI handles network-to-network roaming, while OCPP handles charger-to-backend communication. ### Is OCPI mandatory in Europe? OCPI is not legally mandated by any European regulation. However, the EU Alternative Fuels Infrastructure Regulation (AFIR), which took effect in April 2024, requires that all public charging stations offer ad-hoc (contract-free) access and interoperable payment. While AFIR does not specify a protocol, meeting its interoperability requirements in practice requires roaming capability, and OCPI is the dominant protocol for achieving this. ### Can I use OCPP without OCPI? Yes. [OCPP](/blog/what-is-ocpp) manages communication between your chargers and your [CSMS (Charging Station Management System)](/blog/what-is-csms) — OCPP 1.6 Central System, industry slang CPMS. You only need OCPI if you want to enable roaming -- allowing drivers from other networks to use your chargers, or allowing your drivers to use chargers on other networks. Many small CPOs operate OCPP-managed networks for years before adding OCPI when they are ready to join a roaming ecosystem. ### What is the difference between OCPI and OICP? OCPI is an open community protocol governed by the EVRoaming Foundation, with its specification freely available on GitHub. OICP (Open InterCharge Protocol) is developed and controlled by Hubject, with its specification available under NDA. Both protocols enable roaming between charging networks. OCPI has broader industry adoption and supports peer-to-peer connections, while OICP is tightly integrated with Hubject's intercharge network and offers more mature Plug&Charge (ISO 15118) support. ### How long does it take to implement OCPI? Implementation timelines vary significantly based on scope and team experience. A minimum viable OCPI implementation (Credentials, Locations, Tokens, and CDRs) typically takes 2-4 months for a development team new to the protocol. Adding all modules, comprehensive error handling, and hub certification extends this to 4-8 months. The credential handshake and CDR reconciliation logic tend to be the most time-consuming aspects. ### What programming languages can I use for OCPI? OCPI is a REST API specification, so it can be implemented in any language that supports HTTP servers and clients. Common choices in the industry include Python, Java, Go, C#, and Node.js. There are several open-source OCPI libraries on GitHub, though most production implementations are custom-built to handle the specific business logic of tariff calculation, CDR validation, and hub integration. ### Does OCPI support Plug&Charge? OCPI 2.2.1 includes partial support for Plug&Charge through the Tokens module (using the AD_HOC_USER token type and authorization_reference field). However, the full Plug&Charge workflow (ISO 15118 certificate management, contract certificate provisioning) is not part of the OCPI specification. Hubject's OICP protocol currently offers more complete Plug&Charge support through its integrated PKI infrastructure. The EVRoaming Foundation is actively working on enhanced Plug&Charge support for future OCPI versions. ### How does OCPI handle pricing and billing? OCPI handles pricing through two modules: Tariffs (published pricing structures) and CDRs (actual billing records). A CPO publishes its tariffs via the Tariffs module, which the eMSP uses to display estimated costs to drivers. After a session completes, the CPO generates a CDR containing the actual cost calculated against the applicable tariff. The eMSP then invoices the driver based on the CDR. Settlement between CPO and eMSP typically happens monthly through the roaming hub or via direct bilateral agreements. ### Is OCPI used outside of Europe? OCPI adoption originated in Europe but is expanding globally. GIREVE has partners in North Africa, the Middle East, and parts of Asia. Hubject (which supports both OICP and OCPI) reports operating across 70+ countries on four continents. In North America, OCPI adoption is growing as operators seek interoperability, though the market has historically relied more on proprietary integrations. Australia, South Korea, and India are emerging OCPI markets as their public charging networks mature. ### What is the latest version of OCPI? As of 2025, the latest stable version is OCPI 2.2.1, released in 2021. OCPI 3.0 is under development by the EVRoaming Foundation, with expected improvements including better support for Plug&Charge, enhanced smart charging profiles, improved hub functionality, and alignment with ISO 15118-20. Most production deployments today run either 2.1.1 or 2.2.1, with an increasing share migrating to 2.2.1. --- ## OCPP 1.6 vs 2.0.1: Differences, Features & Migration Guide Source: https://ocpplab.com/blog/ocpp-1-6-vs-2-0-1 Compare OCPP 1.6 and 2.0.1 across security, smart charging, the device model, transactions, and ISO 15118 — plus a 5-step migration guide for CPMS teams. **Quick answer:** OCPP 2.0.1 is a major redesign of OCPP 1.6, not a backwards-compatible upgrade. The biggest differences: 2.0.1 has **mandatory security profiles** (1.6 makes them optional via the Security Whitepaper edition 2), a structured **device model** instead of flat config keys, a unified **`TransactionEvent`** instead of separate `StartTransaction`/`StopTransaction`, native **ISO 15118 Plug & Charge** support, and **renamed remote commands** (`RequestStartTransaction` instead of `RemoteStartTransaction`). OCPP 1.6 is still the most widely deployed version; OCPP 2.0.1 is the standard for new high-security and smart-charging deployments. **OCPP 1.6 and OCPP 2.0.1** are the two active versions of the Open Charge Point Protocol, both published by the [Open Charge Alliance (OCA)](https://openchargealliance.org/protocols/open-charge-point-protocol/). OCPP 1.6 is deployed on the vast majority of charge points worldwide (estimated 80%+ of installed base as of 2025), while OCPP 2.0.1 is the standard for new deployments requiring advanced security, [ISO 15118](https://www.iso.org/standard/55366.html) Plug & Charge, and grid-integrated smart charging. Most production [CPMS platforms](/blog/what-is-csms) need to support both versions simultaneously, since operators typically manage mixed fleets of legacy and modern charge points. If you need version-specific validation guidance, start with [OCPP 1.6 testing](/protocols/ocpp-1-6) and [OCPP 2.0.1 testing](/protocols/ocpp-2-0-1). By the numbers — per the [Open Charge Alliance](https://www.openchargealliance.org/) and the official compliance test packs: - **OCPP 1.6 core defines 28 unique actions** across 10 charger-initiated + 19 CPMS-initiated messages (with `DataTransfer` going in both directions). The **OCPP 1.6 Security Whitepaper edition 2** extension adds 11 more, bringing the total to ~39. - **OCPP 1.6 ships with 178 official OCTT (compliance) test cases** (102 Charge Point, 76 Central System). - **OCPP 2.0.1 Edition 2 defines 64 operations** across **16 functional blocks** (A–P), of which 12 blocks (A, B, C, E, F, G, J, K, L, M, N, P) have **365 official Part 6 test cases** (230 Charging Station + 135 CPMS). - OCPP 1.6 schemas are **JSON Schema draft-04**; OCPP 2.0.1 schemas are **JSON Schema draft-06**. ## Quick Comparison: OCPP 1.6 vs 2.0.1 | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|-----------|------------| | **Release Year** | 2015 | 2020 | | **Transport** | WebSocket + SOAP | WebSocket only | | **Message Format** | JSON or SOAP/XML | JSON only | | **Security** | Optional TLS in core; Profiles 0–3 via Security Whitepaper edition 2 (opt-in extension) | Mandatory security profiles (1, 2, 3) | | **ISO 15118** | Not natively supported | Full Plug & Charge support | | **Smart Charging** | Basic charge profiles | Composite schedules with priorities | | **Device Model** | Limited configuration keys (~50) | Comprehensive variable system (500+) | | **Firmware Updates** | Basic via `UpdateFirmware`; `SignedUpdateFirmware` available via Security Whitepaper edition 2 | Signed firmware, secure boot | | **Transaction Handling** | Start/Stop based | Event-driven with automatic recovery | | **Display Messages** | Not available | Remote display control | | **Cost Information** | Not available | Real-time pricing updates | | **Reservations** | Basic connector reservation | EVSE-based reservations | | **Certificate Management** | Not in core; `InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds` available via Security Whitepaper edition 2 | Full PKI certificate lifecycle | | **Message Count** | 28 core actions (plus 11 in the Security Whitepaper) | **64 operations** (Edition 2). Do not count Errata or OCPP-J as operations | | **Adoption** | Dominant on the installed base | Standard for new high-security deployments | ## Why Is Security the Biggest Difference? Security is the single most significant improvement in OCPP 2.0.1. In OCPP 1.6, TLS encryption is optional — many production deployments run unencrypted [WebSocket connections](/blog/ocpp-websocket-guide), relying solely on network-level security. ### OCPP 1.6 Security In core OCPP 1.6: - TLS is optional and often not implemented - No standardized authentication mechanism - No certificate management - No signed firmware updates - Vulnerable to man-in-the-middle attacks on unencrypted connections The **OCPP 1.6 Security Whitepaper edition 2** is an optional extension that retroactively adds the same security model later made mandatory in OCPP 2.0.1: four security profiles (0/1/2/3, with different numbering than 2.0.1), certificate management messages (`InstallCertificate`, `SignCertificate`, `CertificateSigned`, `DeleteCertificate`, `GetInstalledCertificateIds`), signed firmware updates (`SignedUpdateFirmware`, `SignedFirmwareStatusNotification`), and security event reporting (`SecurityEventNotification`). The catch is that whitepaper support is opt-in per deployment, so much of the installed 1.6 base still runs without it. ### OCPP 2.0.1 Security Profiles OCPP 2.0.1 defines three mandatory security profiles (numbered differently from the 1.6 Security Whitepaper edition 2 — 2.0.1 starts at Profile 1, while 1.6 starts at Profile 0): | Profile | Authentication | Encryption | Use Case | |---------|---------------|------------|----------| | **Profile 1** | HTTP Basic Auth | None (ws://) | Trusted private networks only | | **Profile 2** | HTTP Basic Auth | TLS with server certificate (wss://) | Standard production deployments | | **Profile 3** | Mutual TLS (client + server certificates) | Full mTLS (wss://) | High-security enterprise deployments | Profile 3 provides the strongest security: the charger and CPMS authenticate each other with X.509 certificates, preventing unauthorized devices from connecting. OCPP 2.0.1 also adds: - **Signed firmware updates**: Cryptographic verification prevents malicious firmware - **Secure boot**: Ensures only authorized firmware runs on the charge point - **Certificate lifecycle management**: Install, update, and revoke certificates remotely ## How Does Smart Charging Compare? [Smart charging](/blog/smart-charging-explained) capabilities differ substantially between versions. ### OCPP 1.6 Smart Charging OCPP 1.6 supports `SetChargingProfile` with basic schedule periods. Each profile contains a stack level and a sequence of time-based power limits. **Limitations:** - Profiles apply per connector only - No station-wide power distribution - No external constraint handling (grid operator limits) - No composite schedule calculation on the charger - Basic priority system (stack levels 0-99) ### OCPP 2.0.1 Smart Charging OCPP 2.0.1 introduces composite schedules and a hierarchical profile system: - **Charging Station profiles**: Apply power limits to the entire station - **EVSE profiles**: Apply limits per EVSE (charging point) - **Transaction profiles**: Apply limits per active session - **External constraints**: Grid operator limits override local profiles - **Composite schedules**: Charger calculates the effective schedule from all active profiles - **Cost-based optimization**: Charge when electricity is cheapest | Capability | OCPP 1.6 | OCPP 2.0.1 | |-----------|----------|------------| | Per-connector limits | Yes | Yes | | Per-station limits | No | Yes | | Grid operator constraints | No | Yes | | Composite schedule calculation | No (CPMS-side only) | Yes (charger-side) | | Cost-based charging | No | Yes | | Discharge (V2G) | No | Foundational ISO 15118 in 2.0.1; ISO 15118-20 / V2G is OCPP 2.1 (not in OCPPLab) | ## How Do the Versions Handle ISO 15118 and Plug & Charge? [ISO 15118](/blog/iso-15118-plug-and-charge) is the standard for high-level communication between EVs and chargers, enabling Plug & Charge — where the vehicle authenticates automatically when plugged in, with no RFID card or app needed. **OCPP 1.6** has no native ISO 15118 support. Some implementations use the `DataTransfer` message as a workaround, but this is non-standard and inconsistent across vendors. **OCPP 2.0.1** provides full ISO 15118 integration: - Certificate-based vehicle authentication - Contract certificate installation and updates - Signed metering data for billing accuracy - Vehicle-to-Grid (V2G) communication support If your roadmap includes Plug & Charge, OCPP 2.0.1 is required. ## How Does Transaction Handling Differ? ### OCPP 1.6 Transactions follow a simple Start/Stop model: 1. `StartTransaction.req` → CPMS assigns a transaction ID 2. `MeterValues` sent periodically during charging 3. `StopTransaction.req` → Transaction ends **Problem**: If the charger loses connectivity between Start and Stop, the transaction can become orphaned. Recovery requires manual intervention or custom workarounds. ### OCPP 2.0.1 Transactions use an event-driven model: 1. `TransactionEvent(Started)` → New transaction 2. `TransactionEvent(Updated)` → Meter values, status changes 3. `TransactionEvent(Ended)` → Transaction complete **Key improvement**: Each event is independently transmitted and can be queued offline. When connectivity is restored, events are sent in order. The CPMS can reconstruct the complete transaction from the event stream, eliminating orphaned transactions. | Aspect | OCPP 1.6 | OCPP 2.0.1 | |--------|----------|------------| | Model | Start/Stop | Event-driven | | Offline handling | Transaction may be lost | Events queued and replayed | | Meter values | Separate MeterValues message | Embedded in TransactionEvent | | ID assignment | CPMS assigns ID (integer) | Charging Station assigns ID (string, 1–36 chars; UUID is common but not required) | ## How Does Device Management Differ? ### OCPP 1.6 Device configuration uses key-value pairs via `GetConfiguration` and `ChangeConfiguration`. There are approximately 50 standardized configuration keys, with vendors often adding proprietary extensions. ### OCPP 2.0.1 The comprehensive **Device Model** replaces configuration keys with a structured variable system: - **Components**: Logical parts of the charger (Connector, EVSE, Controller) - **Variables**: Attributes of each component (CurrentLimit, Temperature, FirmwareVersion) - **Characteristics**: Metadata about each variable (read-only, writable, data type, unit) This provides 500+ standardized variables covering every aspect of charger configuration, monitoring, and diagnostics. The device model makes it possible to manage any charger without vendor-specific documentation. ## Message Types Comparison ### Messages Only in OCPP 2.0.1 | Message | Purpose | |---------|---------| | `SetDisplayMessage` | Control charger screen content | | `CostUpdated` | Real-time pricing display | | `Get15118EVCertificate` | ISO 15118 certificate management | | `GetInstalledCertificateIds` | PKI certificate inventory | | `InstallCertificate` | Install new certificates | | `DeleteCertificate` | Remove certificates | | `NotifyReport` | Comprehensive device status reporting | | `SetVariables` / `GetVariables` | Device model management | | `SetNetworkProfile` | Network configuration | | `PublishFirmwareStatusNotification` | Firmware distribution status | | `ReportChargingProfiles` | Smart charging profile reporting | | `ClearedChargingLimit` | External constraint acknowledgment | ### Messages in Both Versions (with improvements in 2.0.1) | Message | 1.6 Behavior | 2.0.1 Improvement | |---------|-------------|-------------------| | `BootNotification` | Basic charger registration | Includes reason (PowerUp, Watchdog, etc.) | | `StatusNotification` | Per-connector status | Per-EVSE + per-connector status | | `FirmwareUpdate` | HTTP download | Signed firmware with integrity check | | `RemoteStartTransaction` | Start by ID tag | Start with charging profile + EVSE selection | ## When Should You Use Which Version? ### Choose OCPP 1.6 if: - You need maximum compatibility with existing chargers - Your network consists primarily of AC Level 2 chargers - ISO 15118 Plug & Charge is not on your roadmap - You need to ship a working product quickly on a budget ### Choose OCPP 2.0.1 if: - Security is a top priority (regulatory or enterprise requirements) - You need ISO 15118 Plug & Charge support - You're building a new platform from scratch - You need advanced smart charging for grid integration - You're deploying DC fast chargers with complex billing - You want future-proof architecture ### Best Practice: Support Both Most modern CPMS platforms support OCPP 1.6 and 2.0.1 simultaneously. A typical production network has: - Legacy AC chargers on OCPP 1.6 - New DC fast chargers on OCPP 2.0.1 - The CPMS handles protocol translation internally ## Migration Guide: OCPP 1.6 to 2.0.1 ### Step 1: Assess Your Current Implementation Audit your OCPP 1.6 message handlers. Map each handler to its 2.0.1 equivalent: - `StartTransaction` / `StopTransaction` → `TransactionEvent` - `GetConfiguration` / `ChangeConfiguration` → `GetVariables` / `SetVariables` - `MeterValues` → Embedded in `TransactionEvent(Updated)` ### Step 2: Implement the Device Model The device model is the biggest architectural change. You'll need: - A database schema for Components, Variables, and their Characteristics - Handlers for `GetBaseReport`, `NotifyReport`, `GetVariables`, `SetVariables` - A mapping layer from your existing configuration to the device model ### Step 3: Migrate Transaction Handling Replace Start/Stop transaction logic with the event-driven model: - Handle `TransactionEvent` with Started, Updated, and Ended types - Implement event sequencing and offline event replay - Update your billing system to work with event streams ### Step 4: Add Security Profiles Implement at least Security Profile 2 (TLS with server certificate): - Configure your WebSocket server for TLS - Implement HTTP Basic Auth over TLS - Set up certificate management for Profile 3 ### Step 5: Test Thoroughly Testing the migration is critical. You need to validate: - Both protocol versions running simultaneously - Backward compatibility with existing 1.6 chargers - All new 2.0.1 message flows - Security profile negotiation - Smart charging composite schedules [OCPPLab](/blog/ocpp-testing-guide) lets you run OCPP 1.6 and 2.0.1 virtual chargers side by side, test migration scenarios, and validate all [error handling paths](/blog/ocpp-error-codes-reference) without physical hardware. ## How Do You Test Both OCPP Versions? Validating an OCPP implementation across both versions requires hundreds of test cases covering message flows, error scenarios, edge cases, and version-specific features. Physical charger testing is impractical at this scale. **OCPPLab** provides: - Side-by-side OCPP 1.6 and 2.0.1 virtual chargers - 100+ pre-built device model profiles from real charger vendors - Automated test suites covering all message types in both versions - Security profile testing (Profile 1, 2, and 3) - Smart charging composite schedule validation - Load testing with 10,000+ concurrent connections across both versions [Start your free simulation](/dashboard) and test both OCPP versions in minutes. ## Frequently Asked Questions ### Can a CPMS support both OCPP 1.6 and 2.0.1 simultaneously? Yes, and most production CPMS platforms do. The CPMS detects the protocol version during the WebSocket handshake (via the `Sec-WebSocket-Protocol` header) and routes messages to the appropriate handler. This is essential since real-world networks have mixed fleets. ### Is OCPP 2.0.1 backward compatible with 1.6? No. OCPP 2.0.1 is a major protocol revision with different message structures, a new device model, and event-driven transactions. A charger running 1.6 cannot communicate with a CPMS that only supports 2.0.1, and vice versa. The CPMS must implement both versions independently. ### Which OCPP version do new chargers support? Many new commercial chargers support both OCPP 1.6 and 2.0.1. They commonly ship with 1.6 as the default and offer 2.0.1 via firmware update. DC fast charger manufacturers (ABB, Tritium, Kempower) generally have stronger 2.0.1 support than AC charger manufacturers. ### When will OCPP 1.6 be deprecated? The Open Charge Alliance has not announced a deprecation date for OCPP 1.6. Given the massive installed base, 1.6 will remain relevant for many years. However, new deployments are increasingly moving to 2.0.1, and OCA's focus is on the 2.x line. ### What is OCPP 2.1? OCPP 2.1 is a **published** Open Charge Alliance specification (2025), not an unpublished future minor of 2.0.1. It adds ISO 15118-20 (bidirectional charging / V2G), improved smart charging, and richer tariff handling. OCPPLab implements **OCPP 1.6 and OCPP 2.0.1 only** — it does not negotiate `ocpp2.1` and has no 2.1 action library. ### How many message types does each version have? OCPP 1.6 core defines **28 unique actions** (plus 11 in the Security Whitepaper edition 2). OCPP 2.0.1 Edition 2 defines **64 operations** across functional blocks A–P. Counts of 66 usually include the Errata and OCPP-J pages, which are not operations. Vague “~50+” figures are not the Edition 2 catalog. ### Is OCPP 2.0.1 harder to implement than 1.6? Yes. OCPP 2.0.1 has a larger specification, more message types, mandatory security requirements, and the complex device model. A typical 2.0.1 implementation takes considerably longer than 1.6. However, the result is significantly more robust and future-proof. ### What is the difference between OCPP and OCPI? [OCPP](/blog/what-is-ocpp) manages communication between a charger and its management system (CPMS). [OCPI](/blog/what-is-ocpi) manages roaming between different charging networks, allowing drivers to use any network with a single account. They serve different purposes and are typically both needed in a production charging network. --- ## What Is a CSMS? Charging Station Management System & CPMS Source: https://ocpplab.com/blog/what-is-csms What a CSMS is, how Charging Station Management System differs from CPMS slang and from OCPP 1.6 Central System, and how EV teams build, buy, and test one. **Quick answer:** A **CSMS** (Charging Station Management System) is the OCPP 2.0.1 name for the backend that runs an EV charging network. OCPP 1.6 calls the same role **Central System**. **CPMS** (Charge Point Management System) is industry slang for that backend — it is not a spec acronym, and it does not expand to Charging Station Management System. A **CSMS** is the backend software that operates an EV charging network. It communicates with chargers over [OCPP](/blog/what-is-ocpp), tracks sessions, authorizes drivers, applies pricing, and gives operators the control layer they need to run chargers at scale. This page keeps the familiar **CPMS** search term because operators still type it; the spec names are Central System (1.6) and CSMS (2.0.1). Think of that backend as the "brain" of a charging network — it tells chargers when to start and stop charging, handles driver authorization, collects usage data, and manages billing. If you are building or evaluating one, continue with [CPMS testing](/use-cases/csms-testing), [OCPP 1.6 testing](/protocols/ocpp-1-6), or [platform features](/features). ## What Does a CPMS Do? ### Core Functions | Function | Description | |----------|-------------| | **Charger Management** | Monitor status, configure settings, trigger reboots remotely | | **Authorization** | Validate driver RFID cards, app tokens, or Plug & Charge certificates | | **Transaction Management** | Start, monitor, and stop charging sessions | | **Billing & Payments** | Calculate costs, process payments, generate invoices | | **Smart Charging** | Manage power distribution across chargers based on grid capacity | | **Monitoring & Alerts** | Real-time dashboards, error notifications, uptime tracking | | **Firmware Management** | Push firmware updates to chargers over-the-air | | **Reporting** | Usage analytics, revenue reports, energy consumption data | ### Advanced Functions - **Roaming**: Connect with other networks via [OCPI](/blog/what-is-ocpi) for cross-network charging - **Energy Management**: Integration with grid operators for demand response - **Fleet Management**: Specialized features for commercial fleet charging - **White-Label**: APIs for partners to build their own branded charging apps ## How Does a CPMS Work with OCPP? The CPMS acts as the **server** in the client-server architecture defined by the [Open Charge Alliance's OCPP standard](https://openchargealliance.org/protocols/open-charge-point-protocol/): 1. Charger boots up and connects to the CPMS via WebSocket 2. CPMS receives `BootNotification` and registers the charger 3. Charger sends `StatusNotification` updates (OCPP 1.6 includes Charging; OCPP 2.0.1 uses Available, Occupied, Reserved, Unavailable, Faulted — charging state is on `TransactionEvent`) 4. When a driver taps their RFID card, charger sends `Authorize` request 5. CPMS validates and responds with `Accepted` or `Blocked` 6. Charging session begins, charger sends periodic `MeterValues` 7. Session ends, CPMS processes billing via `StopTransaction` ## What CPMS Platforms Are Available? | Platform | Type | Notable Features | |----------|------|-----------------| | **ChargePoint** | Proprietary | Largest US network, integrated hardware+software | | **EVBox (Everon)** | Commercial | European market leader, strong OCPI support | | **Current** | Commercial | GE-backed, utility-focused | | **Open e-Mobility** | Open Source | Free CPMS with OCPP 1.6/2.0.1 support | | **[SteVe](https://github.com/steve-community/steve)** | Open Source | Java-based, widely used for testing | | **[CitrineOS](https://github.com/citrineos/citrineos)** | Open Source | Modern TypeScript CPMS for OCPP 2.0.1 | ## Should You Build or Buy a CPMS? ### Build Your Own - **Pros**: Full control, custom features, no licensing fees - **Cons**: often a year or more of development, ongoing maintenance, OCPP expertise required - **Best for**: Companies where charging is a core product differentiator ### Buy/License - **Pros**: Fast deployment, proven reliability, vendor handles updates - **Cons**: Licensing costs, less customization, vendor dependency - **Best for**: Companies where charging is a utility, not the core business ### White-Label - **Pros**: Your brand, their technology, faster than building - **Cons**: Limited customization, ongoing fees - **Best for**: Companies wanting branded experience without development ## How to Test a CPMS Whether you're building, buying, or evaluating a CPMS, thorough testing is critical. You need to validate: - OCPP message handling (every [OCPP 1.6 message type](/blog/ocpp-message-types-complete-reference)) - Error scenarios (network drops, invalid messages, timeout handling) - Concurrent connections (can it handle 1,000+ chargers?) - [Smart charging](/blog/smart-charging-explained) algorithms (does load balancing work correctly?) - Firmware update flows (does OTA work reliably?) - Billing accuracy (are transactions calculated correctly?) **OCPPLab** simulates realistic charger behavior so you can test your CPMS without physical hardware. Deploy 1000+ virtual charge points, run automated test suites, and validate every OCPP message flow. ## Frequently Asked Questions ### What is the difference between CSMS and CPMS? They refer to the same backend role, with different names. **CSMS** (Charging Station Management System) is the OCPP 2.0.1 spec term. **Central System** is the OCPP 1.6 spec term. **CPMS** (Charge Point Management System) is industry and product slang. Expanding CPMS as Charging Station Management System mixes the CSMS expansion with the wrong acronym. ### Can a CPMS manage chargers from different manufacturers? Yes — that's the entire purpose of OCPP. Any OCPP-compliant charger from any manufacturer can connect to any OCPP-compliant CPMS. ### How much does a CPMS cost? Ranges from free (open source like SteVe or Open e-Mobility) through per-charger monthly subscriptions for commercial platforms, up to substantial enterprise licensing fees. Costs depend on features, scale, and support level. --- ## CPO vs eMSP: Understanding EV Charging Roles Explained Source: https://ocpplab.com/blog/cpo-vs-emsp-explained CPO vs eMSP: the two core EV charging roles. Learn how they differ, their business models, and the 7-step OCPI flow that connects chargers to EV drivers. **Quick answer:** A CPO (Charge Point Operator) owns, installs, and operates physical EV charging stations and their CPMS backend, while an eMSP (e-Mobility Service Provider) is the customer-facing layer giving drivers apps, authentication, billing, and roaming access. They connect through the OCPI protocol, and a single company can act as both. The EV charging ecosystem has two fundamental roles: **CPO (Charge Point Operator)** and **eMSP (e-Mobility Service Provider)**. Understanding the difference is essential for anyone building, operating, or integrating with charging infrastructure. ## CPO: Charge Point Operator A **CPO** owns, installs, and operates physical EV charging stations. They are responsible for: - **Hardware**: Purchasing, installing, and maintaining chargers - **Network Operations**: Monitoring uptime, handling faults, scheduling maintenance - **Grid Connection**: Managing electrical infrastructure and grid integration - **CPMS Management**: Running the [CPMS backend](/blog/what-is-csms) that controls chargers via [OCPP](/blog/what-is-ocpp), the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) communication standard - **Location Management**: Securing sites, managing access, signage ### CPO Examples - **Fastned** (Netherlands) — Operates highway fast-charging stations - **IONITY** (Europe) — Joint venture operating ultra-fast chargers across Europe - **ChargePoint** (US) — Both CPO and eMSP, operating an extensive US charging network - **Allego** (Europe) — Pan-European charging network operator - **EVgo** (US) — Operates DC fast charging stations ## eMSP: e-Mobility Service Provider An **eMSP** provides EV drivers with access to charging stations. They are the customer-facing layer: - **Driver Apps**: Mobile applications for finding, starting, and paying for charging - **Authentication**: RFID cards, app-based tokens, [Plug & Charge](/blog/iso-15118-plug-and-charge) certificates ([ISO 15118-20](https://www.iso.org/standard/77845.html)) - **Billing**: Processing payments, subscriptions, and invoice generation - **Roaming**: Enabling access to multiple CPO networks via [OCPI](/blog/what-is-ocpi), the [EVRoaming Foundation](https://evroaming.org/ocpi/) standard - **Customer Support**: Handling driver inquiries and disputes ### eMSP Examples - **Plugsurfing** — Aggregates multiple charging networks into one app - **NewMotion (Shell Recharge)** — Provides roaming access across Europe - **Chargemap** — French eMSP with pan-European coverage - **Electromaps** — Spanish eMSP expanding across Southern Europe ## What Are the Key Differences Between CPO and eMSP? | Aspect | CPO | eMSP | |--------|-----|------| | **Core Asset** | Physical chargers | Customer relationships | | **Revenue Model** | Energy sales, site fees | Service fees, subscriptions | | **Technology** | CPMS + OCPP | Driver app + OCPI | | **Customer** | Site owners, grid operators | EV drivers | | **Key Metric** | Uptime, utilization rate | Active users, sessions | | **Capex** | High (hardware + installation) | Low (software-based) | ## How Do CPOs and eMSPs Work Together? The connection between CPOs and eMSPs happens via the **OCPI protocol**: 1. CPO publishes charger locations, availability, and pricing via OCPI 2. eMSP pulls this data and shows it to drivers in their app 3. Driver selects a charger and requests to start charging 4. eMSP sends authorization token to CPO via OCPI 5. CPO validates and starts the charging session via OCPP 6. After charging, CPO sends a CDR (Charge Detail Record) to eMSP 7. eMSP bills the driver, then settles with the CPO ## Can a Company Be Both CPO and eMSP? Yes — and many are. Companies like ChargePoint, Tesla, and Shell Recharge operate as both: - **As CPO**: They operate their own charging stations - **As eMSP**: They provide driver-facing apps and roaming access This vertical integration simplifies the user experience but can limit interoperability if not connected to roaming networks. ## How Do You Test CPO and eMSP Integrations? Building or integrating CPO/eMSP functionality requires testing: - **OCPP flows** (CPO side): Charger communication, authorization, [smart charging](/blog/smart-charging-explained) - **OCPI flows** (Roaming): Location sharing, session management, CDR exchange - **End-to-end scenarios**: Driver authenticates via eMSP app → CPO starts charging **OCPPLab** supports both OCPP and OCPI testing, letting you simulate the full charging ecosystem — from charger to CPMS to roaming hub — without any physical infrastructure. --- ## Smart Charging Explained: How EV Load Management Works Source: https://ocpplab.com/blog/smart-charging-explained Learn how smart charging controls EV power with OCPP charging profiles across 6 strategies—load balancing, peak shaving, demand response, ISO 15118, and V2G. **Quick answer:** Smart charging dynamically controls the power delivered to EVs based on grid capacity, energy prices, renewable availability, and driver needs. Using OCPP charging profiles, it orchestrates when and how fast vehicles charge, cutting peak demand substantially, lowering costs, preventing grid overload, and enabling load balancing, peak shaving, demand response, and vehicle-to-grid revenue. **Smart charging** is the ability to dynamically control the power delivered to electric vehicles based on real-time constraints such as grid capacity, energy prices, renewable availability, and driver preferences. Rather than every EV drawing maximum power the moment it plugs in, smart charging orchestrates when and how fast vehicles charge — reducing costs, preventing grid overload, and enabling new revenue streams. As EV adoption accelerates, smart charging is no longer optional. Without it, a parking garage with 50 Level 2 chargers each pulling 7.4 kW would need a 370 kW grid connection — equivalent to a small industrial facility. Smart charging can substantially reduce that peak demand, making large-scale EV charging deployable without massive electrical upgrades. ## How Does Smart Charging Work with OCPP? [OCPP](/blog/what-is-ocpp), maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), defines smart charging through **Charging Profiles** — structured instructions sent from the [CPMS](/blog/what-is-csms) to the charge point that specify power limits over time. ### OCPP 1.6 Smart Charging In [OCPP 1.6](/blog/ocpp-1-6-vs-2-0-1), smart charging uses the `SetChargingProfile` and `GetCompositeSchedule` messages: - **ChargingProfile**: Defines a power schedule with time-based periods - **ChargingProfilePurpose**: `ChargePointMaxProfile`, `TxDefaultProfile`, or `TxProfile` (these three names are OCPP 1.6) - **ChargingRateUnit**: Power limits expressed in Watts (W) or Amps (A) - **StackLevel**: Priority system for overlapping profiles (higher level wins) ### OCPP 2.0.1 Smart Charging OCPP 2.0.1 significantly enhances smart charging capabilities: - **Composite Schedules**: The CPMS can request the charge point to calculate the effective schedule from all active profiles - **Charging Needs**: The EV communicates its energy requirements to the CPMS via [ISO 15118](/blog/iso-15118-plug-and-charge) - **Profile purposes**: `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, `TxDefaultProfile`, `TxProfile`. There is no `ChargePointMaxProfile` in 2.0.1 - **External Constraints**: The Charging Station reports external power limits to the CSMS via `NotifyChargingLimit`, while the CSMS applies grid constraints using `SetChargingProfile` with `ChargingStationExternalConstraints` - **Cost-Based Charging**: Real-time energy prices influence charging schedules - **Priority-Based Stacking**: More granular control with separate profiles per EVSE and per transaction ## What Are the Main Load Balancing Strategies? Load balancing distributes available electrical capacity across multiple charge points. There are two primary approaches: ### Static Load Balancing A fixed power budget is divided equally (or according to preset rules) among connected EVs. The total never exceeds the site's electrical capacity. **Example**: A site with 100 kW capacity and 10 connected EVs allocates 10 kW per charger, regardless of whether some EVs are nearly full or just started. ### Dynamic Load Balancing Power allocation adjusts in real-time based on actual site consumption, EV battery state, driver priority, and departure time. **Example**: The same 100 kW site monitors building consumption in real-time. If the building uses only 40 kW, 60 kW is available for EV charging and distributed based on each vehicle's needs. ### Comparison of Load Balancing Strategies | Aspect | Static Load Balancing | Dynamic Load Balancing | |--------|----------------------|----------------------| | **Implementation** | Simple, rule-based | Complex, requires real-time data | | **Hardware Required** | Basic OCPP chargers | Smart meter + OCPP chargers + energy management system | | **Grid Efficiency** | Moderate (conservative limits) | High (uses full available capacity) | | **User Experience** | Predictable but slower | Optimized charging speeds | | **Cost** | Lower setup cost | Higher setup, lower operating cost | | **Best For** | Small sites (under 10 chargers) | Large sites, fleet depots, commercial buildings | | **OCPP Feature** | OCPP 1.6 `ChargePointMaxProfile` (2.0.1: `ChargingStationMaxProfile`) | `TxProfile` with real-time updates | ## What Is Peak Shaving? **Peak shaving** reduces maximum power drawn from the grid during high-demand periods. This is critical because commercial electricity tariffs often include **demand charges** — fees based on your highest 15-minute power peak in a billing period. Smart charging achieves peak shaving by: 1. **Monitoring** real-time site power consumption via smart meters 2. **Predicting** upcoming peak periods using historical data and schedules 3. **Throttling** EV charging power when site consumption approaches the peak threshold 4. **Restoring** full charging power when demand drops A well-implemented peak shaving strategy can meaningfully reduce electricity costs for sites with significant EV charging load. ## What Is Demand Response? **Demand response** is when EV charging adjusts in response to [signals from the grid operator or energy market](https://www.ferc.gov/power-sales-and-markets/demand-response). Unlike peak shaving (which serves the site owner), demand response serves the broader electrical grid. Use cases include: - **Grid balancing**: Reducing EV charging when the grid is stressed - **Renewable integration**: Increasing charging when solar or wind generation is high - **Price response**: Shifting charging to low-price periods in real-time energy markets - **Frequency regulation**: Rapid power adjustments to stabilize grid frequency OCPP 2.0.1 supports demand response through external charging limit notifications and cost-based charging profiles. ## How Does ISO 15118 Enable Smart Charging? **[ISO 15118](https://www.iso.org/standard/55366.html)** is the communication protocol between the EV and the charger (not to be confused with OCPP, which is between the charger and the CPMS). It enables two transformative smart charging features: ### Plug and Charge The EV automatically authenticates and begins charging when plugged in — no app, no RFID card. Authentication happens via X.509 digital certificates exchanged between the EV and the charger. OCPP 2.0.1 integrates with ISO 15118 to relay these certificates to the CPMS. ### Charging Needs Communication Via ISO 15118, the EV can communicate: - Current battery state of charge (SoC) - Target SoC and departure time - Maximum acceptable charging power - Energy amount requested This information flows from the EV through the charger (via ISO 15118) to the CPMS (via OCPP 2.0.1), enabling truly optimized smart charging. ## What Is Vehicle-to-Grid (V2G)? **Vehicle-to-Grid (V2G)** enables EVs to feed stored energy back to the grid. Instead of being passive consumers, EVs become mobile batteries that can support grid stability. V2G requires: - **Bidirectional chargers**: Hardware capable of both AC/DC charging and discharging - **[ISO 15118-20](https://www.iso.org/standard/77845.html)**: The latest version of the vehicle-charger protocol with V2G support - **OCPP 2.0.1**: Backend communication for managing bidirectional energy flows - **Grid integration**: Agreements with utilities and grid operators ### V2G Use Cases - **Peak shaving**: Discharge EVs during peak demand, recharge overnight - **Frequency regulation**: Rapid charge/discharge cycles to stabilize grid frequency - **Renewable buffering**: Store excess solar during the day, discharge in the evening - **Emergency backup**: Use EV batteries as backup power for buildings ## Smart Charging Strategy Comparison | Strategy | Goal | Complexity | Savings Potential | OCPP Support | |----------|------|-----------|-------------------|--------------| | **Static Load Balancing** | Prevent overload | Low | Moderate (infrastructure) | 1.6 + 2.0.1 | | **Dynamic Load Balancing** | Optimize utilization | Medium | High (infrastructure) | 1.6 + 2.0.1 | | **Peak Shaving** | Reduce demand charges | Medium | Moderate (electricity) | 1.6 + 2.0.1 | | **Demand Response** | Grid flexibility | High | Revenue from grid services | 2.0.1 | | **Time-of-Use Optimization** | Shift to cheap hours | Low | Modest (electricity) | 1.6 + 2.0.1 | | **V2G** | Bidirectional energy | Very High | Revenue from energy trading | 2.0.1 | ## Testing Smart Charging Smart charging is one of the most complex areas of [OCPP implementation](/blog/ocpp-implementation-guide). A single miscalculation in a charging profile can overload a site's electrical infrastructure or leave EVs undercharged. **OCPPLab** lets you test smart charging scenarios without risking physical hardware: - Simulate multiple EVs with different battery sizes, SoC levels, and departure times - Send and validate charging profiles across OCPP 1.6 and 2.0.1 - Test composite schedule calculations with overlapping profiles - Verify load balancing behavior under various site consumption patterns - Simulate ISO 15118 charging needs communication via OCPP 2.0.1 - Validate peak shaving logic with configurable power thresholds Teams building smart charging features use OCPPLab to test hundreds of edge cases that would be impossible to reproduce with physical chargers — such as 50 EVs simultaneously requesting full power. ## Frequently Asked Questions ### What is the difference between smart charging and managed charging? They are often used interchangeably. "Smart charging" typically refers to the technical capability (OCPP profiles, load management), while "managed charging" is a broader term that includes utility programs and driver-facing features. ### Does smart charging damage EV batteries? No. Smart charging controls the power level within the EV's accepted range. In fact, slower charging through smart charging can extend battery life compared to always charging at maximum power. ### Do all OCPP chargers support smart charging? Most OCPP 1.6 chargers support basic charging profiles, but implementation quality varies. OCPP 2.0.1 chargers are required to support smart charging as part of core protocol compliance. Always verify smart charging support with your charger manufacturer. ### Can smart charging work without ISO 15118? Yes. OCPP-based smart charging works without ISO 15118 — the CPMS sends power limits to the charger based on site-level data. ISO 15118 adds vehicle-specific intelligence (like SoC and departure time) that makes smart charging more precise, but it is not a requirement. ### What hardware do I need for smart charging? At minimum, you need OCPP-capable chargers and a CPMS with smart charging logic. For dynamic load balancing, you also need a smart meter at the grid connection point. For V2G, you need bidirectional chargers and ISO 15118-20 compatible vehicles. --- ## Complete Guide to EV Charger Testing: Tools & Methods Source: https://ocpplab.com/blog/ev-charger-testing-guide Learn five EV charger testing methods—functional, load, compliance, integration, and regression—plus virtual vs physical best practices to ship a reliable CPMS. **Quick answer:** EV charger testing validates that charging stations, management systems (CPMS), and their integrations work correctly, securely, and at scale. The core methods are functional, load, compliance, integration, and regression testing. Combining virtual emulators with physical hardware validation catches the most issues, while CI/CD automation keeps every CPMS update from breaking existing functionality. **EV charger testing** is the process of validating that charging stations, management systems ([CPMS](/blog/what-is-csms)), and their integrations work correctly, securely, and at scale. As charging networks grow from dozens to thousands of stations, the cost of a single undetected bug multiplies — a firmware issue that bricks one charger is annoying, but one that bricks hundreds of chargers simultaneously is catastrophic. Testing is not a one-time activity. Every CPMS update, every new charger model onboarded, and every protocol change requires regression testing to ensure nothing breaks. Organizations that invest in structured testing programs tend to detect far more issues before production than those relying on field testing alone. ## Why Does EV Charger Testing Matter? The consequences of inadequate testing are severe and measurable: - **Revenue loss**: A charger offline at a busy location can lose meaningful revenue for every hour it stays down - **Driver frustration**: Failed charging sessions are among the most common complaints from EV drivers - **Safety risks**: Incorrect power management can damage vehicles or create electrical hazards - **Compliance failures**: Industry organizations like the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) and roaming platforms ([GIREVE](/integrations/gireve-ocpi-testing), [Hubject](/integrations/hubject-oicp-testing)) require protocol compliance - **Scaling failures**: Systems that work with a handful of chargers often fail at thousands ## What Are the Types of EV Charger Testing? ### 1. Functional Testing Functional testing validates that individual [OCPP](/blog/what-is-ocpp) operations work correctly in isolation and in sequence. **What to test:** - BootNotification and registration flow - Authorization (RFID, app-based, [Plug & Charge](https://www.iso.org/standard/55366.html)) - Start and stop transaction flows - MeterValues reporting accuracy and intervals - StatusNotification transitions (Available, Preparing, Charging, Finishing, Faulted) - Remote operations (RemoteStartTransaction, Reset, UnlockConnector) - Firmware update lifecycle - Configuration key management (GetConfiguration, ChangeConfiguration) ### 2. Load Testing Load testing measures how your CPMS performs under realistic and peak traffic conditions. **What to test:** - Concurrent WebSocket connections (100, 500, 1,000, 10,000 charge points) - Message throughput (MeterValues from all stations every 30 seconds) - Database write performance under sustained load - API response times during peak usage - Memory and CPU utilization over extended periods - Connection recovery after CPMS restart ### 3. Compliance Testing Compliance testing verifies that your implementation follows the [OCPP specifications](https://openchargealliance.org/protocols/open-charge-point-protocol/) precisely. **What to test:** - All required message fields are present and correctly typed - Optional fields are handled gracefully when absent - Error responses follow the [OCPP error code specification](/blog/ocpp-error-codes-reference) - Message sequencing adheres to protocol state machines - [Security profile](/blog/ocpp-security-profiles-explained) implementation (Basic Auth, TLS client certificates) - [OCA certification](https://openchargealliance.org/certification-program/) test cases ### 4. Integration Testing Integration testing validates end-to-end workflows across multiple system components. **What to test:** - Full charging session lifecycle (plug in to CDR generation) - [OCPI roaming](/blog/how-to-implement-ocpi-roaming) flow (eMSP authorization through CPO charge point) - Payment processing integration - Energy management system integration (smart charging signals) - Fleet management system integration - Mobile app to CPMS to charge point flow ### 5. Regression Testing Regression testing ensures that new changes do not break existing functionality. **What to test:** - All previously passing test cases after any code change - Charger model-specific behaviors after CPMS updates - Protocol version compatibility ([1.6 and 2.0.1](/blog/ocpp-1-6-vs-2-0-1) simultaneously) - Database migration integrity - API backward compatibility ## Physical vs Virtual Testing: Which Should You Use? The traditional approach of testing with physical chargers is increasingly impractical. Here is how the two approaches [compare in depth](/blog/virtual-vs-physical-testing): | Aspect | Physical Testing | Virtual Testing (Emulators) | |--------|-----------------|---------------------------| | **Setup Cost** | $2,000-50,000 per charger | $0 per virtual station | | **Scale** | Limited by hardware budget | 1,000+ stations instantly | | **Speed** | Days to configure hardware | Minutes to deploy | | **Reproducibility** | Low — hardware state varies | High — identical conditions every run | | **Edge Cases** | Difficult to simulate faults | Easy — inject any error or delay | | **CI/CD Integration** | Not practical | Native integration | | **Protocol Versions** | Limited to charger firmware | Any version, any configuration | | **Concurrency** | Limited by physical space and power | Unlimited parallel testing | | **Charger Models** | One model per physical unit | Simulate 100+ models | | **Location** | Requires lab or field access | Anywhere with internet | Physical testing still has its place — final validation on actual hardware before deployment catches driver-facing UX issues and electrical integration problems that no emulator can replicate. The best testing strategy combines both. ## How Do You Automate EV Charger Testing? ### CI/CD Pipeline Integration Every commit to your CPMS should trigger automated OCPP tests: ``` 1. Developer pushes code 2. CI builds and deploys to staging 3. Virtual charge points connect automatically 4. Automated test suite runs (200+ test cases) 5. Results reported — pass/fail with detailed logs 6. Deploy to production only on full pass ``` ### Test Scenario Design Structure your test scenarios in layers: - **Smoke tests** (run on every commit): 10-20 critical path tests — boot, authorize, charge, stop - **Regression suite** (run nightly): 200+ tests covering all OCPP operations - **Load tests** (run weekly): Sustained traffic simulation with 1,000+ connections - **Compliance suite** (run before releases): Full OCA certification test coverage ### Common Bugs Found in CPMS Implementations From testing hundreds of CPMS platforms, these are the most frequent issues: | Bug Category | Example | Frequency | |-------------|---------|-----------| | **Message Parsing** | Rejecting valid optional fields, incorrect date format handling | Very Common | | **State Management** | Allowing RemoteStart on a Charging connector | Common | | **Concurrency** | Race condition when two transactions start simultaneously | Common | | **Meter Values** | Incorrect energy calculation from sampled vs clock-aligned values | Common | | **Reconnection** | Losing transaction state when charge point reconnects | Frequent | | **Authorization Cache** | Stale cache allowing revoked RFID tags | Frequent | | **Firmware Update** | Not handling FirmwareStatusNotification timeouts | Frequent | | **Smart Charging** | Incorrect composite schedule calculation with overlapping profiles | Common | | **Error Handling** | Crashing on malformed JSON instead of returning CALLERROR | Very Common | | **Memory Leaks** | WebSocket connections not properly closed on disconnect | Frequent | ## What Are EV Charger Testing Best Practices? ### 1. Test with Multiple Charger Behaviors Different charger manufacturers implement OCPP differently within the specification. Your CPMS must handle all valid variations: - Some chargers send MeterValues every 10 seconds, others every 60 seconds - Boot sequence timing varies between manufacturers - StatusNotification transition patterns differ - Optional message fields may or may not be present ### 2. Test Failure Scenarios Extensively Happy-path testing catches only a fraction of production issues. Focus on: - Network disconnection during active transactions - Charger power loss and recovery - Invalid or expired authorization tokens - Concurrent operations on the same connector - CPMS restart with active sessions ### 3. Maintain a Charger Compatibility Matrix Track which charger models and firmware versions you have validated: | Charger Model | Firmware | OCPP Version | Tested | Status | |--------------|----------|-------------|--------|--------| | ABB Terra AC | 1.8.2 | 1.6 | Yes | Passed | | EVBox Elvi | 5.1.0 | 1.6 | Yes | Passed | | Wallbox Pulsar | 3.4.1 | 1.6 | Yes | Issues | | Alfen Eve | 8.2.0 | 2.0.1 | No | Pending | ### 4. Monitor Production as a Testing Signal Production is the ultimate test environment. Instrument your CPMS to detect: - Failed transaction rates per charger model - OCPP message error rates - WebSocket disconnection frequency - Average transaction duration anomalies ## Testing with OCPPLab **OCPPLab** is purpose-built for EV charger testing at scale. It provides: - **Virtual Charge Points**: Deploy up to 1,000+ stations that behave like real chargers, supporting OCPP 1.6 and 2.0.1 - **Device Model Library**: Simulate specific charger brands and firmware versions with manufacturer-accurate OCPP behavior - **Scenario Engine**: Script complex multi-step test scenarios including error injection, delays, and power fluctuations - **CI/CD Integration**: Trigger test suites from your deployment pipeline and get pass/fail results programmatically - **Detailed Logging**: Full WebSocket message capture with timestamps for debugging failed tests Teams using OCPPLab report shortening their QA cycle from weeks to days, while increasing test coverage from a small set of manual tests to hundreds of automated scenarios. For a deeper walkthrough, see our [complete guide to testing a CPMS](/blog/how-to-test-csms-complete-guide). ## Frequently Asked Questions ### How many test cases do I need for a production CPMS? A minimum viable test suite covers the core OCPP operations. A comprehensive suite for production readiness typically includes a few hundred test cases covering happy paths, error scenarios, edge cases, and charger-specific behaviors. ### Should I test OCPP 1.6 and 2.0.1 separately? Yes. While many message concepts are similar, the protocol differences are significant enough that separate test suites are necessary. Most CPMS platforms support both versions simultaneously, so your regression suite must cover both. ### Can virtual testing replace physical testing entirely? Not entirely. Virtual testing should handle the large majority of your validation — protocol compliance, load testing, regression, and edge cases. Physical testing is still necessary for final hardware integration validation, electrical safety verification, and driver-facing UX testing. ### How often should regression tests run? Smoke tests should run on every commit. Full regression suites should run at least nightly. Load tests should run weekly or before major releases. Compliance suites should run before any production deployment. ### What is the cost of not testing? A single critical OCPP bug reaching production can cost far more in emergency fixes, lost revenue, and customer churn than it would have cost to catch the same bug in testing — often by an order of magnitude or more. --- ## OCPP WebSocket Communication: A Developer's Guide Source: https://ocpplab.com/blog/ocpp-websocket-guide Learn how OCPP uses WebSocket for real-time EV charger communication: connection lifecycle, 3 JSON message types, heartbeat, reconnection, and WSS security. **Quick answer:** OCPP uses WebSocket as the transport layer for real-time, bidirectional messaging between EV chargers and the Central System (CPMS). A persistent connection lets either side send messages instantly without HTTP polling. Messages travel as JSON arrays (CALL, CALLRESULT, CALLERROR), with heartbeats, exponential-backoff reconnection, and TLS/WSS security profiles keeping connections reliable and secure. **OCPP WebSocket communication** is the transport layer that enables real-time, bidirectional messaging between EV chargers and their [Central System (CPMS)](/blog/what-is-csms). [OCPP](https://openchargealliance.org/protocols/ocpp-protocols/) is the open standard maintained by the Open Charge Alliance, and WebSocket is the channel it rides on. Unlike traditional REST APIs where the client polls for updates, WebSocket maintains a persistent connection — allowing either side to send messages at any time without the overhead of repeated HTTP handshakes. Understanding how OCPP uses WebSocket is essential for every developer building or integrating with EV charging infrastructure. Most OCPP bugs in production trace back to WebSocket-level issues: connection drops, message ordering problems, or security misconfigurations. ## Why Does OCPP Use WebSocket? OCPP chose WebSocket over alternatives for specific technical reasons: - **Bidirectional**: Both the charger and CPMS can initiate messages. The CPMS needs to send commands (RemoteStart, Reset) to chargers without the charger polling for them - **Persistent**: A single TCP connection stays open for hours or days, eliminating reconnection overhead - **Low latency**: Messages arrive in milliseconds, critical for real-time operations like smart charging profile updates - **Firewall friendly**: WebSocket upgrades from HTTP, traversing corporate firewalls and proxies that block raw TCP - **Lightweight**: Minimal framing overhead compared to HTTP request/response cycles OCPP 1.6 supports both WebSocket (JSON) and SOAP, while [OCPP 2.0.1](https://openchargealliance.org/protocols/open-charge-point-protocol/) uses WebSocket exclusively, having dropped SOAP support entirely. For a fuller breakdown of the differences, see [OCPP 1.6 vs 2.0.1](/blog/ocpp-1-6-vs-2-0-1). ## How Does the WebSocket Connection Lifecycle Work? ### 1. WebSocket Handshake The charge point initiates a WebSocket connection to the CPMS, following the upgrade handshake defined in [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455). The URL follows a specific pattern: ``` ws://CPMS.example.com/ocpp/CP001 wss://CPMS.example.com/ocpp/CP001 ``` The path typically includes the charge point identity (`CP001`). The CPMS uses this to identify which charger is connecting. The HTTP upgrade request includes OCPP-specific subprotocols: ``` GET /ocpp/CP001 HTTP/1.1 Host: CPMS.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Protocol: ocpp1.6, ocpp2.0.1 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== ``` The CPMS responds with the selected subprotocol: ``` HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Protocol: ocpp1.6 ``` ### 2. BootNotification Immediately after the WebSocket connection is established, the charge point sends a `BootNotification` message: ```json [2, "19223201", "BootNotification", { "chargePointVendor": "EVManufacturer", "chargePointModel": "FastCharger-50", "chargePointSerialNumber": "SN-001234", "firmwareVersion": "3.2.1" }] ``` The CPMS responds with the registration status and heartbeat interval: ```json [3, "19223201", { "status": "Accepted", "currentTime": "2025-02-13T10:00:00.000Z", "interval": 300 }] ``` ### 3. Normal Operation Once registered, the charge point and CPMS exchange messages for charging operations, status updates, and remote commands. The connection remains open indefinitely. ### 4. Disconnection and Reconnection When the connection drops (network failure, CPMS restart, charger power cycle), the charge point is responsible for reconnecting. The CPMS must restore the charger's state from the last known information. ## OCPP JSON Message Format OCPP defines three message types, all transmitted as JSON arrays over WebSocket. For the full catalog of actions carried inside these envelopes, see the [OCPP message types reference](/blog/ocpp-message-types-complete-reference): ### CALL (Message Type 2) A request message sent by either party. Format: ```json [2, "uniqueMessageId", "ActionName", {payload}] ``` **Example — OCPP 1.6 charger sends StatusNotification** (`Charging` is a 1.6 connector status; OCPP 2.0.1 uses Occupied and reports charging on `TransactionEvent`): ```json [2, "msg-4501", "StatusNotification", { "connectorId": 1, "errorCode": "NoError", "status": "Charging", "timestamp": "2025-02-13T10:15:00.000Z" }] ``` **Example — CPMS sends RemoteStartTransaction:** ```json [2, "cmd-7890", "RemoteStartTransaction", { "connectorId": 1, "idTag": "RFID-ABC123" }] ``` ### CALLRESULT (Message Type 3) A successful response to a CALL. The message ID must match the original CALL: ```json [3, "uniqueMessageId", {payload}] ``` **Example — CPMS responds to StatusNotification:** ```json [3, "msg-4501", {}] ``` **Example — Charger responds to RemoteStartTransaction:** ```json [3, "cmd-7890", { "status": "Accepted" }] ``` ### CALLERROR (Message Type 4) An error response to a CALL. Used when the message cannot be processed: ```json [4, "uniqueMessageId", "errorCode", "errorDescription", {errorDetails}] ``` **Example — Unknown action error:** ```json [4, "msg-9999", "NotImplemented", "This action is not supported", {}] ``` ### Standard OCPP Error Codes These are the codes carried in the `errorCode` slot of a CALLERROR; for a complete walkthrough with troubleshooting tips, see the [OCPP error codes reference](/blog/ocpp-error-codes-reference). | Error Code | Meaning | |-----------|---------| | `NotImplemented` | Requested action is not known or supported | | `NotSupported` | Action is recognized but not supported | | `InternalError` | Internal error in the receiver | | `ProtocolError` | Payload does not conform to protocol | | `SecurityError` | Security issue (e.g., invalid certificate) | | `FormationViolation` | Payload is syntactically incorrect | | `PropertyConstraintViolation` | Property value violates constraints | | `OccurrenceConstraintViolation` | Required property is missing | | `TypeConstraintViolation` | Property has wrong type | | `GenericError` | Catch-all for other errors | ## How Does the Heartbeat Mechanism Work? The **Heartbeat** message serves two purposes: confirming the charge point is still connected, and synchronizing its clock with the CPMS. ```json [2, "hb-001", "Heartbeat", {}] ``` ```json [3, "hb-001", { "currentTime": "2025-02-13T10:05:00.000Z" }] ``` The heartbeat interval is set by the CPMS in the `BootNotification` response, and operators commonly configure it to anywhere from under a minute to several minutes depending on fleet size and tolerance for stale state. If the CPMS does not receive a heartbeat within the expected window, it should consider the charge point offline. **Important implementation details:** - Any OCPP message resets the heartbeat timer — if a charger sends `MeterValues`, it does not need to send a separate Heartbeat until the next interval - The CPMS should allow some tolerance (e.g., 2x the interval) before marking a charger offline, accounting for network jitter - Charge points should use the `currentTime` from the response to correct clock drift ## What Are the Best Reconnection Strategies? Network disconnections are inevitable. A robust OCPP implementation needs a reliable reconnection strategy. ### Exponential Backoff The recommended approach for charge point reconnection: ``` Attempt 1: Wait 1 second Attempt 2: Wait 2 seconds Attempt 3: Wait 4 seconds Attempt 4: Wait 8 seconds ... Maximum: Wait 300 seconds (5 minutes) ``` Adding random jitter (0-30% of the wait time) prevents the "thundering herd" problem — where hundreds of chargers reconnect simultaneously after a CPMS restart. ### CPMS-Side Reconnection Handling When a charge point reconnects, the CPMS must: 1. Accept the new WebSocket connection 2. Process the `BootNotification` (may return `Accepted` or `Pending`) 3. Request current status via `TriggerMessage` for `StatusNotification` 4. Reconcile any transactions that were active during disconnection 5. Re-apply any pending charging profiles or configuration changes ### Connection Monitoring | Strategy | Implementation | Typical Interval | |----------|---------------|-----------------| | **OCPP Heartbeat** | Application-level ping | 60-300 seconds | | **WebSocket Ping/Pong** | Protocol-level keepalive | 30-60 seconds | | **TCP Keepalive** | OS-level connection check | 60-120 seconds | | **Load Balancer Health Check** | Infrastructure-level | 10-30 seconds | Use multiple layers. WebSocket Ping/Pong detects dead connections faster than OCPP Heartbeat, while TCP Keepalive catches cases where both endpoints think the connection is alive but an intermediate device has dropped it. ## How Do TLS and WSS Secure OCPP? Production OCPP deployments must use encrypted WebSocket connections (WSS — WebSocket Secure): ### OCPP Security Profiles OCPP 2.0.1 defines three mandatory security profiles. The numbering below matches the **OCPP 2.0.1 specification**. For a deeper treatment, see [OCPP security profiles explained](/blog/ocpp-security-profiles-explained). | Profile | Authentication | Encryption | Required by OCPP 2.0.1? | |---------|---------------|-----------|-------------| | **Profile 1** | HTTP Basic Auth | None — unencrypted (ws://) | Yes (at minimum) | | **Profile 2** | HTTP Basic Auth | TLS with server certificate (wss://) | Optional, recommended | | **Profile 3** | TLS client certificate (mutual auth) | TLS with client + server certificates (wss://) | Optional, strongest | > **OCPP 1.6 uses different numbering.** The OCPP 1.6 Security Whitepaper edition 2 defines Profiles **0–3**, where 1.6 Profile 0 ≈ 2.0.1 Profile 1 (ws:// + Basic Auth), 1.6 Profile 1 ≈ 2.0.1 Profile 2 (wss:// + Basic Auth), and 1.6 Profile 2 ≈ 2.0.1 Profile 3 (mTLS). 1.6 Profile 3 adds a signed Basic Auth token on top of mTLS. Plain-core 1.6 deployments without the whitepaper extension use ws:// with no authentication. ### TLS Implementation Checklist - Use TLS 1.2 or higher (TLS 1.3 preferred) - Validate server certificates on the charge point side - For Profile 3, manage client certificate provisioning and rotation - Pin certificates or use a dedicated CA for your charging network - Configure cipher suites to exclude weak algorithms (no RC4, no 3DES) - Handle certificate expiration gracefully with automated renewal ## How Do You Debug OCPP WebSocket Issues? ### Common Problems and Solutions **Connection refused**: The CPMS is not listening on the expected port or the charge point URL path is incorrect. Verify the WebSocket endpoint URL and that the subprotocol header matches. **Connection drops after 60 seconds**: A load balancer or proxy is closing idle connections. Ensure WebSocket Ping/Pong frames are being sent, or configure the infrastructure to allow long-lived connections. **Messages not received**: Check that both sides handle WebSocket fragmentation correctly. Some OCPP libraries buffer incomplete frames, and large messages (like firmware update notifications) may be split across multiple WebSocket frames. **Authentication failures**: Verify that HTTP Basic Auth credentials or TLS client certificates are correctly configured. Check certificate chain completeness — intermediate CA certificates are a frequent omission. **Message ordering issues**: OCPP requires that a CALL is answered before the next CALL is sent in the same direction. However, both the charger and CPMS can each have one outstanding CALL simultaneously — one in each direction. Sending a second CALL in the same direction before receiving a response to the first causes undefined behavior. ## Testing WebSocket Communication with OCPPLab Debugging WebSocket issues with physical chargers is time-consuming — you cannot easily inspect what the charger is sending, inject specific errors, or reproduce timing-sensitive bugs. **OCPPLab** provides full visibility into OCPP WebSocket communication: - **Message Inspector**: View every WebSocket frame with exact timestamps, including Ping/Pong - **Connection Simulation**: Test reconnection scenarios, slow networks, and connection drops - **Error Injection**: Send malformed JSON, unknown actions, or out-of-sequence messages to test CPMS error handling - **Security Profile Testing**: Validate all OCPP security profiles including TLS client certificate authentication - **Multi-Connection Load**: Open hundreds of simultaneous WebSocket connections to stress-test your CPMS Whether you are debugging a single charger's connection issue or validating that your CPMS handles 5,000 concurrent WebSocket connections, OCPPLab gives you the control and visibility that physical hardware cannot. ## Frequently Asked Questions ### Can OCPP work over HTTP instead of WebSocket? OCPP 1.6 also has a SOAP variant (OCPP 1.6S), but it is legacy and rarely used in new deployments. OCPP 2.0.1 requires WebSocket exclusively. WebSocket is strongly recommended for all new implementations because it enables server-initiated messages (which HTTP cannot do without polling). ### How many WebSocket connections can a CPMS handle? This depends entirely on the CPMS architecture. A well-optimized CPMS on modern infrastructure can comfortably handle tens of thousands of concurrent WebSocket connections, and far more with horizontal scaling. The bottleneck is typically database writes (MeterValues), not the WebSocket connections themselves. ### What happens to active transactions when WebSocket disconnects? The charge point continues charging locally. Transaction data (MeterValues) is typically queued and sent after reconnection. The CPMS should detect the disconnection and await reconnection, then reconcile any missed data. OCPP 2.0.1 handles this more gracefully than 1.6 with its improved transaction model. ### Should I use a WebSocket library or implement the protocol myself? Always use an established WebSocket library. Implementing the WebSocket protocol from scratch introduces unnecessary risk. For OCPP specifically, use an OCPP library that handles message routing, ID generation, and timeout management on top of the WebSocket layer. ### How do I handle WebSocket connections behind a load balancer? Use sticky sessions (session affinity) to ensure a charge point always connects to the same CPMS instance, or implement a shared session store. The load balancer must support WebSocket upgrade and long-lived connections. Configure appropriate idle timeout values to prevent premature disconnection. --- ## GIREVE Hub Integration: A Complete Guide for CPOs & eMSPs Source: https://ocpplab.com/blog/gireve-hub-integration Learn how to integrate with GIREVE, Europe's leading EV charging roaming hub: OCPI modules, the 5-step certification process, costs, and Hubject comparison. **Quick answer:** GIREVE is Europe's leading EV charging roaming hub, connecting hundreds of CPOs and eMSPs across much of Europe. You connect through a single OCPI 2.1.1 or 2.2.1 integration, then pass registration, technical setup, and certification before going live — reaching millions of drivers without building new infrastructure or hundreds of direct partner connections. **GIREVE** is the leading EV charging roaming platform in Europe, connecting hundreds of [Charge Point Operators (CPOs) and e-Mobility Service Providers (eMSPs)](/blog/cpo-vs-emsp-explained) across much of Europe. Founded in 2013 and based in France, GIREVE operates as a neutral hub that enables interoperability between charging networks — allowing EV drivers to charge on any connected network with a single subscription or payment method. For any company operating or providing access to EV chargers in Europe, connecting to GIREVE is one of the most effective ways to reach millions of EV drivers and expand network coverage without building new infrastructure. ## How Does GIREVE Work? GIREVE operates as a **B2B roaming hub**, sitting between CPOs and eMSPs: 1. **CPOs** connect to GIREVE and publish their charger locations, availability, pricing, and capabilities 2. **eMSPs** connect to GIREVE and receive this aggregated data to display in their driver apps 3. When a driver on eMSP-A wants to use a charger operated by CPO-B, GIREVE routes the authorization request between them 4. After charging, GIREVE handles the CDR (Charge Detail Record) exchange for billing and settlement ### The Hub Model vs Direct Connections Without a hub, a CPO wanting to enable roaming with 50 eMSPs would need 50 separate integrations. A hub reduces this to a single integration: | Approach | Connections for 50 Partners | Maintenance | |----------|---------------------------|-------------| | **Direct (Peer-to-Peer)** | 50 separate integrations | 50 APIs to maintain | | **Hub (via GIREVE)** | 1 integration | 1 API to maintain | This is why roaming hubs have become the standard architecture in European EV charging. ## What Are GIREVE's OCPI Integration Requirements? GIREVE uses **[OCPI (Open Charge Point Interface)](/blog/what-is-ocpi)** as its primary integration protocol, the open roaming standard maintained by the [EVRoaming Foundation](https://evroaming.org/ocpi/). Specifically, GIREVE supports [OCPI 2.1.1 and OCPI 2.2.1](/blog/ocpi-2-1-1-vs-2-2-1). ### Required OCPI Modules To connect with GIREVE, you must implement specific OCPI modules depending on your role: **For CPOs:** | Module | Purpose | Required | |--------|---------|----------| | **Credentials** | Authentication and version handshake | Yes | | **Locations** | Publish charger locations, EVSEs, and connectors | Yes | | **Sessions** | Share real-time charging session data | Yes | | **CDRs** | Send Charge Detail Records for billing | Yes | | **Tariffs** | Publish pricing information | Yes | | **Commands** | Receive remote start/stop commands from eMSPs | Recommended | | **Tokens** | Receive driver authorization tokens | Yes | **For eMSPs:** | Module | Purpose | Required | |--------|---------|----------| | **Credentials** | Authentication and version handshake | Yes | | **Locations** | Receive charger location data from CPOs | Yes | | **Sessions** | Receive real-time charging session data | Yes | | **CDRs** | Receive Charge Detail Records for billing | Yes | | **Tariffs** | Receive pricing information | Yes | | **Commands** | Send remote start/stop commands to CPOs | Recommended | | **Tokens** | Publish driver authorization tokens | Yes | ### Technical Requirements - **REST API**: OCPI is a REST-based protocol using JSON over HTTPS - **Authentication**: Token-based authentication (OCPI credentials exchange) - **TLS**: All connections must use TLS 1.2 or higher - **Availability**: Your OCPI endpoints must maintain high uptime (GIREVE enforces strict availability thresholds) - **Response Time**: API responses should be fast; GIREVE monitors endpoint latency - **Data Quality**: Location data must be accurate and regularly updated For a deeper walkthrough of the underlying protocol flows, see our [guide to implementing OCPI roaming](/blog/how-to-implement-ocpi-roaming). ## How Do You Connect to GIREVE? ### Step 1: Registration Contact GIREVE to initiate the partnership process. You will need to provide: - Company legal information - Technical contact details - Your role (CPO, eMSP, or both) - Network size and geographic coverage - Target OCPI version (2.1.1 or 2.2.1) ### Step 2: Technical Integration GIREVE provides access to their **IOP (Interoperability Platform)**, which includes: - A staging environment for development and testing - Technical documentation and OCPI implementation guides - API endpoints for credential exchange and module registration - Test tools for validating your OCPI implementation ### Step 3: Certification Before going live, GIREVE requires passing their certification process: - **Protocol compliance**: Your OCPI implementation must pass GIREVE's automated test suite - **Data quality**: Location data accuracy is validated (coordinates, addresses, connector types) - **Operational readiness**: Uptime, response time, and error rate thresholds must be met - **Business validation**: Tariff structures and CDR formats are reviewed ### Step 4: Go Live Once certified, your connection is activated in production: - CPOs: Your chargers become visible to all connected eMSPs - eMSPs: You gain access to charger data from all connected CPOs - GIREVE monitors the connection and alerts on any issues ### Step 5: Ongoing Operations After going live, you must maintain: - Real-time data synchronization (location updates, availability changes) - Timely CDR processing (typically within 24 hours of session completion) - Response to GIREVE operational alerts and maintenance windows - OCPI version upgrades when announced ## Why Connect to GIREVE? ### For CPOs - **Increased utilization**: Access to millions of EV drivers across a large network of connected eMSPs - **Revenue growth**: Roaming transactions generate additional revenue without marketing spend - **European coverage**: Visibility across charging networks throughout Europe - **Simplified billing**: GIREVE handles financial settlement with all roaming partners - **Regulatory compliance**: AFIR (Alternative Fuels Infrastructure Regulation) encourages roaming ### For eMSPs - **Network expansion**: Offer your drivers access to a large European charging network — as of early 2026, [GIREVE's roaming barometer](https://www.gireve.com/) reported roughly 695,000 connected charge points across Europe - **Single integration**: One connection replaces hundreds of direct CPO integrations - **Real-time data**: Live availability, pricing, and session monitoring - **Billing automation**: CDR exchange and settlement handled by the platform - **Competitive advantage**: Comprehensive charging coverage attracts more subscribers ## How Does GIREVE Compare to Other Roaming Hubs? GIREVE is one of several roaming hubs operating in Europe, each with different strengths and protocol support (see our [OCPI vs OICP vs OCHP comparison](/blog/ocpi-vs-oicp-vs-ochp)): | Feature | GIREVE | Hubject | e-clearing.net | |---------|--------|---------|----------------| | **Headquarters** | France | Germany | Belgium | | **Founded** | 2013 | 2012 | 2009 | | **Primary Protocol** | OCPI | OICP (proprietary) | OCPI + OCHP | | **OCPI Support** | Native (2.1.1, 2.2.1) | Via adapter | Native | | **Plug & Charge** | Developing | Yes (ISO 15118 PKI) | No | | **Geographic Strength** | France, Southern Europe | Germany, Central Europe | Benelux, Nordics | | **Pricing Model** | Per-transaction fee | Per-transaction fee | Per-transaction fee | | **Certification Process** | Required | Required | Required | | **Open Protocol** | Yes (OCPI) | No (OICP proprietary) | Yes (OCPI/OCHP) | ### Choosing a Roaming Hub Many companies connect to multiple hubs to maximize coverage. Consider: - **Geography**: Choose the hub strongest in your target markets - **Protocol**: If you already have OCPI implemented, GIREVE and e-clearing.net are natural fits - **Plug & Charge**: If [ISO 15118 Plug & Charge](/blog/iso-15118-plug-and-charge) is a priority, Hubject currently leads with its PKI infrastructure - **Partners**: Check which hub your key partners are already connected to - **Cost**: Compare per-transaction fees and any fixed membership costs ## Common Integration Challenges ### Data Quality Issues The most frequent reason for failed GIREVE certification is poor location data: - GPS coordinates that do not match the actual charger location - Missing or incorrect connector type information - Outdated availability data (chargers shown as available when offline) - Incomplete address information ### Tariff Complexity European EV charging tariffs are complex, varying by time of day, energy consumed, charging duration, and subscription status. Your OCPI tariff module must accurately represent these structures. ### CDR Reconciliation Discrepancies between CPO and eMSP CDR records cause billing disputes. Common causes include: - Time zone mismatches in session timestamps - Rounding differences in energy measurements - Missing or delayed CDR delivery - Inconsistent tariff application ### Performance Under Load GIREVE sends location and session updates at high frequency. Your OCPI endpoints must handle sustained traffic without degradation — particularly the Locations and Sessions modules during peak hours. ## Testing Your GIREVE Integration GIREVE integration involves complex multi-party flows that are difficult to test without a controlled environment. Issues discovered during certification can delay your go-live by weeks or months. **OCPPLab** helps you prepare for [GIREVE integration testing](/integrations/gireve-ocpi-testing) by letting you: - **Simulate OCPI endpoints**: Test your CPO or eMSP implementation against realistic OCPI traffic patterns - **Validate data quality**: Generate and verify location data, tariff structures, and CDR formats before submitting to GIREVE - **Test end-to-end flows**: Simulate a complete roaming transaction from eMSP authorization through CPO charging session to CDR settlement - **Load test OCPI modules**: Verify your endpoints handle the traffic volume GIREVE will generate - **Debug protocol issues**: Inspect every OCPI request and response with full payload logging - **Test OCPP + OCPI together**: Validate that your CPMS correctly translates between OCPP charger communication and OCPI roaming data Organizations that pre-validate their OCPI implementation using OCPPLab typically pass GIREVE certification on the first attempt, avoiding costly delays. ## Frequently Asked Questions ### How long does GIREVE integration take? The typical timeline is 3-6 months from initial contact to production. Technical integration takes 4-8 weeks, certification 2-4 weeks, and business/legal setup runs in parallel. ### How much does GIREVE connection cost? GIREVE charges a per-transaction fee for roaming sessions. The exact pricing depends on your volume and is negotiated during the partnership setup. There may also be an annual platform fee. ### Can I connect to GIREVE and Hubject simultaneously? Yes. Many CPOs and eMSPs connect to multiple hubs. Your OCPI implementation serves GIREVE, and a separate [OICP](https://github.com/hubject/oicp) (or OCPI adapter) integration serves Hubject. Be aware of potential duplicate roaming sessions if a partner is on both hubs. ### Do I need OCPI 2.2.1 or is 2.1.1 sufficient? GIREVE supports both versions. OCPI 2.1.1 covers all core roaming functionality and is currently the most widely deployed. OCPI 2.2.1 adds hub-specific features and improved tariff handling. GIREVE may eventually require 2.2.1, so implementing it from the start is advisable. ### Is GIREVE only for European networks? GIREVE's primary coverage is Europe, but they are expanding internationally. If your network operates outside Europe, check with GIREVE about coverage in your region. For Asia-Pacific or North American roaming, other platforms may provide better coverage. ### What is the difference between GIREVE and eMI3? eMI3 (eMobility ICT Interoperability Innovation) defines data standards and identifiers (like the eMI3 ID format for EVSEs and tokens). GIREVE uses eMI3 standards within its platform. They are complementary rather than competing — eMI3 defines the data format, GIREVE provides the exchange platform. --- ## ISO 15118 & Plug and Charge: EV Authentication Guide Source: https://ocpplab.com/blog/iso-15118-plug-and-charge ISO 15118 enables Plug and Charge: automatic EV authentication with no app or card. Learn how it works with OCPP 2.0.1, its 7-step flow, and how to test it. **Quick answer:** ISO 15118 is the communication standard between EVs and chargers that enables Plug and Charge — plug in and your EV automatically authenticates and starts charging with no app, RFID card, or credit card. It uses TLS encryption and X.509 certificates, requires OCPP 2.0.1 on the backend, and also enables Vehicle-to-Grid. **[ISO 15118](https://www.iso.org/standard/55366.html)** is the International Organization for Standardization's communication standard between electric vehicles and charging stations. It enables **Plug and Charge (PnC)** — the ability to simply plug in your EV and have it automatically authenticate and start charging, with no app, RFID card, or credit card needed. The [ISO 15118-20](https://www.iso.org/standard/77845.html) revision (2022) extends the standard with full bidirectional / V2G support. Think of it as the EV equivalent of tapping your phone to pay — except you just plug in the cable. ## How Does Plug and Charge Work? 1. **Driver plugs in** the charging cable 2. **Vehicle and charger** establish a TLS-secured communication channel 3. **Vehicle presents** its digital certificate (installed by the manufacturer or eMSP) 4. **Charger forwards** the certificate to the [CPMS](/blog/what-is-csms) for validation 5. **CPMS validates** the certificate chain and authorizes the session 6. **Charging begins** automatically — no user interaction needed 7. **Billing** is handled via the contract associated with the vehicle's certificate In practice the handshake completes in a few seconds, so the experience feels close to instant from plug-in to charging. ## How Does ISO 15118 Work With OCPP? **Core [OCPP 1.6](/protocols/ocpp-1-6)** does not support ISO 15118. It lacks the message types needed for vehicle-side certificate provisioning (no `Get15118EVCertificate`). The optional **OCPP 1.6 Security Whitepaper edition 2** does add `SignCertificate`, `CertificateSigned`, `InstallCertificate`, `DeleteCertificate`, and `GetInstalledCertificateIds` for CPMS-charger certificate management (see the OCA's [Using ISO 15118 Plug & Charge with OCPP 1.6](https://openchargealliance.org/ocpp-info-whitepapers/using-iso-15118-plug-charge-with-ocpp-1-6/) whitepaper and our [OCPP security profiles](/blog/ocpp-security-profiles-explained) guide), but it does not include the EV-contract-certificate flow that Plug & Charge requires. **[OCPP 2.0.1](/protocols/ocpp-2-0-1)** has [full ISO 15118 support](https://openchargealliance.org/protocols/open-charge-point-protocol/) including: - `Get15118EVCertificate` — Vehicle requests a new charging contract certificate (2.0.1-only) - `CertificateSigned` — CPMS installs certificates on the charger (also in 1.6 Security Whitepaper edition 2) - `SignCertificate` — Charger requests its own security certificate (also in 1.6 Security Whitepaper edition 2) - Certificate management for the entire PKI (Public Key Infrastructure) chain | Feature | OCPP 1.6 | OCPP 2.0.1 | |---------|----------|------------| | Plug and Charge | Not supported (no `Get15118EVCertificate`) | Full support | | CPMS-charger certificate management | Available via Security Whitepaper edition 2 (opt-in) | Complete PKI integration in core | | Vehicle Communication | Not available | ISO 15118-2 and 15118-20 | | Bidirectional Charging | Not supported | V2G ready | ## What Is Vehicle-to-Grid (V2G)? ISO 15118 also enables **Vehicle-to-Grid (V2G)** — the ability for EVs to send power back to the grid during peak demand. This requires: - Bidirectional chargers (DC) - ISO 15118-20 support (the latest revision) - Grid operator integration - OCPP 2.0.1 for backend communication V2G turns every parked EV into a potential grid battery, helping utilities manage peak loads through [smart charging](/blog/smart-charging-explained) and enabling EV owners to earn money by selling electricity back. ## Testing ISO 15118 with OCPPLab Testing Plug and Charge is complex because it involves: - Certificate chain validation (Root CA → Sub-CA → Leaf certificates) - TLS handshake between vehicle and charger - OCPP 2.0.1 certificate management messages - Multiple failure scenarios (expired certs, revoked certs, unknown CAs) **OCPPLab** simulates the complete ISO 15118 flow including certificate exchange, allowing you to test Plug and Charge without physical vehicles or chargers. ## Frequently Asked Questions ### Which EVs support Plug and Charge? A growing number of automakers — spanning both premium and mainstream brands — support Plug and Charge on select models, and the list continues to expand as ISO 15118 adoption widens. Check your specific vehicle and network for current support. ### Is Plug and Charge secure? Yes. ISO 15118 uses TLS encryption and PKI (Public Key Infrastructure) with X.509 certificates — the same security model used for HTTPS on the web. ### Do I need OCPP 2.0.1 for Plug and Charge? For the backend (CPMS) side, yes. OCPP 2.0.1 is required to manage certificates and process ISO 15118 authentication. The charger itself communicates with the vehicle via ISO 15118 directly. --- ## EV Charging Glossary: 50+ Terms Every Developer Should Know Source: https://ocpplab.com/blog/ev-charging-glossary A developer reference defining 50+ EV charging terms across OCPP, OCPI, CPMS, CPO, eMSP, ISO 15118, and smart charging, so you can ship integrations faster. **Quick answer:** This glossary defines 50+ EV charging terms developers need, spanning protocols like OCPP and OCPI, roles like CPO, CPMS, and eMSP, plus concepts like AC and DC charging, authorization, CDRs, smart charging, and ISO 15118 Plug and Charge. It's a quick reference whether you're building a CPMS, deploying chargers, or developing a driver app. The EV charging industry has its own vocabulary. Whether you're a developer building a [CPMS](/blog/what-is-csms), a [CPO](/blog/cpo-vs-emsp-explained) deploying chargers, or an eMSP building a driver app, this glossary covers every term you need to know. ## A ### AC Charging Charging an EV using alternating current. The vehicle's onboard charger converts AC to DC. AC delivers lower power than DC, which generally suits longer dwell times such as home, workplace, or overnight charging. Also called Level 1 (120V) or Level 2 (240V) charging in North America. ### AFIR (Alternative Fuels Infrastructure Regulation) EU regulation requiring member states to deploy public EV charging infrastructure along major highways. Mandates ad-hoc payment access at all public chargers. ### Authorization The process of verifying whether an EV driver is allowed to use a charging station. Methods include RFID cards, mobile apps, Plug and Charge ([ISO 15118](/blog/iso-15118-plug-and-charge)), and credit card terminals. ## B ### BootNotification The first OCPP message a charger sends when connecting to a CPMS. Contains the charger's vendor, model, serial number, and firmware version. The CPMS responds with an accepted/rejected status and a heartbeat interval. ## C ### CDR (Charge Detail Record) A record of a completed charging session used for billing. Contains start time, end time, energy delivered, costs, and authentication details. Exchanged between CPO and eMSP via [OCPI](/blog/what-is-ocpi). ### Connector The physical plug on a charging station. Common types: Type 1 (J1772), Type 2 (Mennekes), CCS1, CCS2, CHAdeMO, Tesla NACS. ### CPO (Charge Point Operator) The company that owns and operates physical EV charging stations. Responsible for hardware, maintenance, and network operations. ### Central System OCPP 1.6 name for the backend that charge points connect to. OCPP 2.0.1 renamed this role **CSMS**. ### CPMS (Charge Point Management System) Industry and product slang for the charger backend. Not an OCPP spec term. Do not expand CPMS as Charging Station Management System — that expansion belongs to **CSMS**. See [What is a CSMS](/blog/what-is-csms). ### CSMS (Charging Station Management System) OCPP 2.0.1 name for the backend that charging stations connect to. Handles authorization, billing, monitoring, and remote operations over [OCPP](/blog/what-is-ocpp). OCPP 1.6 uses **Central System**. ## D ### DC Fast Charging Charging an EV using direct current, bypassing the vehicle's onboard charger. Delivers substantially higher power than AC, which can charge a battery in tens of minutes rather than hours, making it common at highway and rapid-charging sites. ### Demand Response Programs where charging is adjusted based on grid conditions. During peak demand, charging power is reduced. During surplus (e.g., high solar/wind production), charging is increased. ## E ### eMSP (e-Mobility Service Provider) A company that provides EV drivers with access to charging stations. Offers apps, RFID cards, and billing. Connects to CPOs via OCPI for roaming. ### EVSE (Electric Vehicle Supply Equipment) Technical term for an EV charging station. Includes the charger, connector, cable, and safety systems. ## G ### GIREVE A major EV charging roaming hub in Europe. Connects a large number of CPOs and eMSPs via OCPI, enabling cross-network charging access. ## H ### Heartbeat A periodic OCPP message sent by a charger to its CPMS to confirm the connection is alive. The interval is set by the CPMS in the BootNotification response. ### Hubject A global roaming platform for EV charging. Uses both OCPI and its proprietary [OICP protocol](https://github.com/hubject/oicp). Known for its Plug&Charge PKI infrastructure. ## I ### IdTag In OCPP 1.6, the identifier used to authorize a charging session. The [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) defines it as a string of up to 20 characters, representing an RFID card UID, app token, or other identifier. ### ISO 15118 International standard for communication between EVs and chargers. Enables Plug and Charge (automatic authentication) and Vehicle-to-Grid (V2G). The bidirectional power transfer requirements are defined in [ISO 15118-20](https://www.iso.org/standard/77845.html). ## L ### Load Balancing Distributing available electrical capacity across multiple chargers to prevent circuit overload. Can be static (fixed limits) or dynamic (real-time adjustment based on actual consumption). ## M ### MeterValues OCPP message containing energy meter readings from a charger. Includes data like energy consumed (Wh), power (W), voltage (V), current (A), and state of charge (%). ## O ### OCA (Open Charge Alliance) The [organization that develops and maintains the OCPP protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/). Members include charger manufacturers, CPMS vendors, and energy companies. ### OCPI (Open Charge Point Interface) [Open protocol for EV charging roaming](https://evroaming.org/ocpi/). Enables data exchange between CPOs and eMSPs for cross-network charging. Current version: 2.2.1. ### OCPP (Open Charge Point Protocol) Open standard for communication between EV chargers and CPMS backends. Uses WebSocket transport with JSON messages. Current versions: [1.6 and 2.0.1](/blog/ocpp-1-6-vs-2-0-1). ### OICP (Open InterCharge Protocol) Hubject's proprietary roaming protocol. Alternative to OCPI for connecting CPOs and eMSPs. ## P ### Peak Shaving Reducing power consumption during periods of high grid demand by lowering charging power or pausing sessions temporarily. ### Plug and Charge Automatic authentication when an EV is plugged into a charger. No app or RFID needed. Enabled by ISO 15118 and OCPP 2.0.1. ## R ### RemoteStartTransaction OCPP message sent from CPMS to charger instructing it to begin a charging session. Used when a driver starts charging via a mobile app. ### Roaming The ability for EV drivers to charge on any network using a single account or app. Enabled by OCPI or OICP protocols. ## S ### Smart Charging Optimizing EV charging based on grid capacity, energy prices, renewable energy availability, or user preferences. Managed via OCPP [charging profiles](/blog/smart-charging-explained). ### StatusNotification OCPP message a charger sends when connector (or EVSE/connector) status changes. **OCPP 1.6** statuses include Available, Preparing, Charging, SuspendedEV, SuspendedEVSE, Finishing, Reserved, Unavailable, and Faulted. **OCPP 2.0.1** StatusNotification is only Available, Occupied, Reserved, Unavailable, or Faulted — charging state lives on `TransactionEvent`. ## T ### TLS (Transport Layer Security) Encryption protocol used to secure OCPP WebSocket connections. OCPP 2.0.1 defines three [security profiles](/blog/ocpp-security-profiles-explained) with increasing TLS requirements. ## V ### V2G (Vehicle-to-Grid) Technology enabling EVs to send stored energy back to the electrical grid. Requires bidirectional chargers and ISO 15118-20 support. ## W ### WebSocket The transport protocol used by OCPP for persistent, bidirectional communication between chargers and CPMS. Enables real-time message exchange without polling. --- ## Test Your Knowledge Ready to put these concepts into practice? **OCPPLab** lets you simulate the entire EV charging ecosystem — deploy virtual chargers, test OCPP/OCPI flows, and validate your CPMS implementation. [Start your free simulation →](/dashboard) --- ## Best CPMS Platforms 2025: Open Source vs Commercial Source: https://ocpplab.com/blog/best-csms-platforms-compared Compare 7 open source and commercial CPMS platforms in 2025 across OCPP, scalability, OCPI roaming, and pricing to choose the right one for your network. **Quick answer:** The best CPMS depends on your scale and needs. Open source options like SteVe, Open e-Mobility, and CitrineOS let you self-host for free, while commercial platforms like ChargePoint, EVBox, Current, and Ampcontrol offer managed scale. Compare OCPP version support, scalability, smart charging, OCPI roaming, pricing, and deployment before choosing. Choosing the right **[CSMS (Charging Station Management System)](/blog/what-is-csms)** — often marketed as a CPMS (Charge Point Management System) — is one of the most consequential decisions for any EV charging business. The platform you select determines your operational capabilities, integration flexibility, scaling ceiling, and long-term cost structure. Get it wrong, and you face expensive migrations, vendor lock-in, or feature gaps that stall your growth. The CPMS market in 2025 spans fully open source projects you can self-host for free, enterprise commercial platforms with per-charger licensing, and everything in between. This guide compares the leading options across the criteria that matter most. ## What Should You Look for in a CPMS? Before evaluating specific platforms, establish your selection criteria. These six factors separate a CPMS that scales with your business from one that becomes a bottleneck. ### OCPP Version Support As of 2024, OCPP 1.6 remains the most widely deployed protocol according to the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), but [OCPP 2.0.1](/blog/ocpp-1-6-vs-2-0-1) is now required for new installations in many markets. Your CPMS should support both versions simultaneously, since your network will likely include chargers running each. Platforms that only support 1.6 are already behind. ### Scalability A CPMS managing 50 chargers has fundamentally different requirements than one managing 50,000. Evaluate whether the platform can handle your projected growth without architectural rewrites. Key metrics: concurrent WebSocket connections, transaction throughput, and MeterValues ingestion rate. ### Smart Charging [Load balancing, peak shaving, and demand response](/blog/smart-charging-explained) capabilities are essential for any deployment beyond a handful of chargers. The CPMS must support OCPP Charging Profiles and, ideally, integrate with energy management systems and grid operator signals. ### OCPI Roaming If you operate a public charging network, [OCPI (Open Charge Point Interface)](/blog/what-is-ocpi) support, maintained by the [EVRoaming Foundation](https://evroaming.org/ocpi/), enables roaming agreements with other networks and platforms like Hubject or Gireve. Without it, only your own registered drivers can use your chargers. ### Pricing Model CPMS pricing ranges from free (open source self-hosting) to per-charger monthly SaaS subscriptions, up to substantial enterprise license fees for large deployments. Evaluate total cost of ownership, including hosting, support, integration development, and internal engineering time. ### Deployment Options Some platforms are SaaS-only, others are self-hosted, and some offer both. SaaS reduces operational burden but limits customization. Self-hosted gives full control but requires infrastructure expertise. Your choice depends on your team's capabilities and regulatory requirements around data residency. ## Which Open Source CPMS Should You Choose? ### SteVe **SteVe** (RWTH Aachen University) is a Java-based CPMS that has been the go-to open source option for years. It is primarily designed for testing and small deployments rather than production-scale operations. **Pros:** - Mature project with years of community development - OCPP 1.6 and partial 2.0 support - Simple setup with Docker or standalone JAR - Well-documented REST API for integration - Active community and academic backing **Cons:** - Not designed for production-scale deployments (better suited to small networks than large fleets) - Limited smart charging capabilities - No built-in OCPI support - Monolithic architecture that is difficult to extend - UI is functional but dated **Best for:** Testing, academic research, proof-of-concept deployments, and small networks under 100 chargers. ### Open e-Mobility **Open e-Mobility** is a more feature-rich open source CPMS built with Node.js and Angular. It targets actual production deployments and includes features typically found only in commercial platforms. **Pros:** - OCPP 1.6 and 2.0.1 support - Built-in smart charging with load balancing - OCPI 2.1.1 roaming support - Multi-tenant architecture for managing multiple sites - Modern web dashboard with real-time monitoring - Active development with regular releases **Cons:** - Steeper learning curve than SteVe - Documentation can lag behind feature development - Smaller community than SteVe - Self-hosted only; requires infrastructure management - Some advanced features are under-documented **Best for:** Mid-size operators who want full control without licensing fees and have the engineering team to manage a self-hosted deployment. ### CitrineOS **[CitrineOS](https://lfenergy.org/projects/citrineos/)** is the newest entrant, built in TypeScript with a modern microservices architecture. It focuses exclusively on OCPP 2.0.1, making it forward-looking but less suitable for legacy charger networks. **Pros:** - Clean, modern TypeScript codebase - OCPP 2.0.1-first design with comprehensive message support - Microservices architecture that scales horizontally - Backed by the Open Charge Alliance - Growing ecosystem of plugins and extensions **Cons:** - No OCPP 1.6 support (by design) - Younger project with smaller community - Fewer production deployments to validate stability - Requires familiarity with TypeScript and modern Node.js tooling - Smart charging and OCPI features still maturing **Best for:** Teams building new CPMS infrastructure on OCPP 2.0.1 who want a modern, extensible foundation. ## Which Commercial CPMS Platforms Lead in 2025? ### ChargePoint **ChargePoint** operates one of the largest charging networks globally and offers an integrated hardware-software platform. Their CPMS is tightly coupled with ChargePoint hardware but also supports third-party chargers via OCPP. **Pros:** - Battle-tested at massive scale (hundreds of thousands of chargers) - Comprehensive driver-facing app and payment processing - Strong fleet management features - Extensive analytics and reporting - 24/7 support and professional services **Cons:** - Primarily designed for ChargePoint hardware; third-party charger support is secondary - Higher pricing tier compared to alternatives - Limited customization; you adapt to their workflows - Vendor lock-in risk if using ChargePoint hardware - Less transparent pricing structure **Best for:** Large enterprises and fleet operators who want a proven, full-stack solution and are willing to pay a premium for reliability and support. ### EVBox / Everon **Everon** (formerly EVBox's software division, now part of the ENGIE ecosystem) is a leading European CPMS with strong OCPI roaming capabilities and multi-country support. **Pros:** - Excellent OCPI roaming support with connections to major European hubs - Multi-currency and multi-language support - Strong presence in European regulatory compliance - Supports chargers from multiple manufacturers via OCPP - White-label options for branded operator portals **Cons:** - Primarily focused on the European market - Pricing can be complex with multiple tiers and add-ons - Some features require higher subscription tiers - Integration with non-European payment systems varies - Customization requires professional services engagement **Best for:** European CPOs needing roaming interoperability and multi-market compliance out of the box. ### Current (GE) **Current** (backed by GE and Daintree) focuses on the intersection of EV charging, building management, and grid integration. Their CPMS is part of a broader energy management platform. **Pros:** - Deep grid and utility integration capabilities - Strong demand response and energy management features - Enterprise-grade reliability backed by GE infrastructure - Integration with building management systems (BMS) - Utility partnership programs and incentive management **Cons:** - Higher complexity for operators who only need basic CPMS functions - Pricing reflects enterprise positioning - Less focused on small to mid-size operators - Feature set can be overwhelming for simple use cases - Slower feature velocity compared to pure-play CPMS vendors **Best for:** Utilities, large commercial real estate operators, and enterprises where EV charging is part of a broader energy strategy. ### Ampcontrol **Ampcontrol** differentiates through AI-driven smart charging optimization. Their platform focuses on maximizing charger utilization and minimizing energy costs through machine learning algorithms. **Pros:** - Advanced AI/ML-based smart charging optimization - Real-time energy price integration and cost minimization - Strong analytics with predictive insights - API-first architecture for custom integrations - Competitive pricing for the feature set **Cons:** - Newer platform with fewer large-scale reference deployments - AI optimization requires sufficient data history to be effective - Smaller partner ecosystem than established players - Documentation and developer resources still growing - Feature breadth narrower than full-platform competitors **Best for:** Operators who prioritize energy cost optimization and want data-driven charging management. ## Comprehensive Comparison Table | Criteria | SteVe | Open e-Mobility | CitrineOS | ChargePoint | EVBox/Everon | Current (GE) | Ampcontrol | |----------|-------|----------------|-----------|-------------|-------------|--------------|------------| | **OCPP 1.6** | Full | Full | None | Full | Full | Full | Full | | **OCPP 2.0.1** | Partial | Full | Full | Full | Full | Partial | Full | | **Smart Charging** | Basic | Good | Growing | Excellent | Good | Excellent | Excellent | | **OCPI Roaming** | None | 2.1.1 | Planned | Proprietary | Excellent | Limited | Limited | | **Scalability** | Low | Medium | High | Very High | High | Very High | Medium | | **Pricing** | Free | Free | Free | $$$ | $$ | $$$ | $$ | | **Deployment** | Self-hosted | Self-hosted | Self-hosted | SaaS | SaaS / Hybrid | SaaS | SaaS / API | | **Customization** | High (source) | High (source) | High (source) | Low | Medium | Low | Medium | | **Support** | Community | Community | Community + OCA | Enterprise | Enterprise | Enterprise | Startup | | **Best For** | Testing | Mid-size CPOs | New builds | Large enterprise | European CPOs | Utilities | Cost optimization | ## When Should You Build Your Own CPMS vs Buy? ### Build Your Own When: - Charging is your core product and primary revenue driver - You need deep integration with proprietary systems (fleet management, energy trading) - Your scale justifies the development investment (typically 5,000+ chargers) - You have an engineering team with OCPP and WebSocket expertise - You need features that no existing platform provides - Regulatory or security requirements mandate full code ownership ### Buy When: - Charging supports your core business but is not the product itself - You need to deploy quickly (weeks, not months) - Your team lacks OCPP protocol expertise - You want vendor-managed updates, security patches, and compliance - Your scale does not justify a dedicated CPMS engineering team ### Consider Open Source When: - You want full control without licensing fees - Your team can manage self-hosted infrastructure - You need a foundation to build custom features on top of - You are in the early stages and want to validate your business model before committing to a commercial license ## How Does OCPPLab Help Test Any CPMS Platform? Regardless of which CPMS you choose, thorough testing is non-negotiable. Physical chargers are expensive, slow to configure, and impossible to use for edge case testing. **OCPPLab** simulates realistic charge point behavior across OCPP 1.6 and 2.0.1, enabling you to: - **Evaluate platforms**: Connect virtual chargers to any CPMS candidate and compare how they handle real OCPP workflows before committing - **Validate integrations**: Test OCPP message flows, error handling, and edge cases without physical hardware - **[Load test at scale](/use-cases/ocpp-load-testing)**: Spin up hundreds or thousands of virtual charge points to verify your CPMS handles production volumes - **Test migrations**: When switching CPMS providers, validate that the new platform handles all your charger models and configurations correctly ## Frequently Asked Questions ### How much does a CPMS cost? Open source platforms (SteVe, Open e-Mobility, CitrineOS) are free to use, but you bear hosting and maintenance costs. Commercial platforms typically charge a per-charger monthly fee for SaaS, with enterprise licenses running considerably higher. Total cost of ownership should include integration development, training, and ongoing support. ### Can I switch CPMS providers? Yes, because OCPP is a standardized protocol. Any OCPP-compliant charger can connect to any OCPP-compliant CPMS. However, switching involves migrating historical data, reconfiguring chargers to point to the new server, updating driver-facing applications, and re-establishing roaming connections. Plan for a multi-month migration depending on network size. ### Do I need OCPI support? If you operate a public charging network and want drivers from other networks to use your chargers (and your drivers to use other networks), yes. OCPI enables roaming interoperability. For private or fleet charging deployments, OCPI is typically unnecessary. For public networks, lack of OCPI support significantly limits your addressable market. ### Can I use multiple CPMS platforms simultaneously? Some operators run different CPMS platforms for different segments of their network (for example, one for AC chargers and another for DC fast chargers). This adds operational complexity but can be practical during migration periods or when specific platforms excel in different areas. ### What OCPP version should my CPMS support? Both OCPP 1.6 and 2.0.1. As of 2024, the majority of deployed chargers still run OCPP 1.6 according to the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/), so dropping support eliminates compatibility with the existing installed base. New charger models increasingly ship with OCPP 2.0.1, so supporting it is necessary for future deployments. A dual-version CPMS is the practical requirement for any serious operator. --- ## OCPP Error Codes: Complete Reference Guide for Developers Source: https://ocpplab.com/blog/ocpp-error-codes-reference Learn all 10 OCPP error codes, the CALLERROR message format, common causes, and step-by-step troubleshooting to debug EV charging infrastructure faster. **Quick answer:** OCPP-J (the JSON variant used in both OCPP 1.6 and 2.0.1) defines exactly **10 error codes** carried in a `CALLERROR` frame: `NotImplemented`, `NotSupported`, `InternalError`, `ProtocolError`, `SecurityError`, `FormationViolation`, `PropertyConstraintViolation`, `OccurrenceConstraintViolation`, `TypeConstraintViolation`, and `GenericError`. A `CALLERROR` frame is `[4, "messageId", "errorCode", "errorDescription", {errorDetails}]`. The same 10 codes are shared between OCPP 1.6 and 2.0.1. **OCPP error codes** are the standardized error responses defined by the Open Charge Point Protocol for communicating failures between charge points and the [CSMS (Charging Station Management System)](/blog/what-is-csms) (OCPP 1.6: Central System). Understanding these errors is essential for every developer building, integrating, or debugging EV charging infrastructure. When an OCPP message cannot be processed, the receiving party responds with a `CALLERROR` message containing a specific error code, a human-readable description, and optional error details. Misinterpreting these errors or failing to handle them correctly leads to stuck transactions, offline chargers, and frustrated drivers. The full error-code enum is normative in the **OCPP-J transport profile** published by the [Open Charge Alliance](https://www.openchargealliance.org/). As defined in the [OCPP 1.6](https://openchargealliance.org/protocols/open-charge-point-protocol/) and [OCPP 2.0.1](https://openchargealliance.org/protocols/open-charge-point-protocol/) specifications, the same **10 error codes apply to both versions** — though, as our [OCPP 1.6 vs 2.0.1 comparison](/blog/ocpp-1-6-vs-2-0-1) explains, their payload schemas differ. This guide covers every OCPP error code, their common causes, and how to resolve them. ## How Does OCPP Error Handling Work? OCPP uses a simple request-response model over [WebSocket](/blog/ocpp-websocket-guide). Every request (CALL) receives either a success response (CALLRESULT) or an error response (CALLERROR). There is no concept of partial success or warnings within the protocol itself. For a breakdown of the three frame types, see our [OCPP message types reference](/blog/ocpp-message-types-complete-reference). ### The CALLERROR Message Format A CALLERROR is a JSON array with message type `4`: ```json [4, "messageId", "errorCode", "errorDescription", {errorDetails}] ``` | Field | Type | Description | |-------|------|-------------| | `4` | Integer | Message type identifier for CALLERROR | | `messageId` | String | Must match the `messageId` of the original CALL | | `errorCode` | String | One of the standardized OCPP error codes | | `errorDescription` | String | Human-readable error explanation (max 255 characters) | | `errorDetails` | Object | Optional JSON object with additional error context | Per the OCPP-J transport profile defined in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/), the `errorDescription` field is capped at 255 characters, while the `errorDetails` object structure is implementation-defined. ### Example CALLERROR Exchange A charger sends an `Authorize` request: ```json [2, "auth-001", "Authorize", { "idTag": "RFID-XYZ789" }] ``` The CPMS encounters an internal database failure and responds: ```json [4, "auth-001", "InternalError", "Authorization service temporarily unavailable", {"retryAfter": 30}] ``` The `messageId` ("auth-001") matches the original request, identifying which CALL this error corresponds to. The `errorDetails` object can contain any additional information the sender deems useful, though its structure is not standardized. ## What Are All 10 OCPP Error Codes? ### NotImplemented **Description:** The requested action is not known by the receiver. **Common Causes:** - Sending an OCPP 2.0.1 action to a CPMS that only supports OCPP 1.6 - Typo in the action name (e.g., "BootNotification" vs "bootNotification" -- OCPP is case-sensitive) - Custom or proprietary actions that the other party does not recognize - Protocol version mismatch between charger and CPMS **How to Fix:** - Verify the action name matches the OCPP specification exactly, including casing - Confirm both parties are using the same OCPP version - Check the WebSocket subprotocol negotiation to ensure version agreement - Review the CPMS or charger documentation for supported action lists ```json [4, "msg-001", "NotImplemented", "Action 'DataTransfer' is not implemented", {}] ``` ### NotSupported **Description:** The action is recognized but intentionally not supported by the receiver. **Common Causes:** - Sending `SetChargingProfile` to a charger that does not support smart charging - Requesting `GetDiagnostics` from a charger without diagnostics capability - Using optional OCPP features that the implementation chose not to include - Feature profile not enabled on the charger firmware **How to Fix:** - Check the charger's supported feature profiles in its documentation or configuration - In OCPP 2.0.1, verify the device model's supported feature list - Implement fallback logic for optional features that may not be universally supported - Do not confuse with `NotImplemented` -- `NotSupported` means the receiver knows the action but explicitly declines it ```json [4, "msg-002", "NotSupported", "SetChargingProfile is not supported by this charge point", {"supportedProfiles": ["Core", "FirmwareManagement"]}] ``` ### InternalError **Description:** An internal error occurred in the receiver that prevented processing the request. **Common Causes:** - Database connection failure on the CPMS - Out-of-memory condition on the charge point - Unhandled exception in the message processing logic - Downstream service unavailable (payment gateway, authorization service) - File system full on the charge point (preventing log or cache writes) **How to Fix:** - Check server/charger logs for the underlying exception or error - Monitor system resources (CPU, memory, disk, database connections) - Implement retry logic with exponential backoff on the calling side - Ensure all downstream dependencies have health checks and circuit breakers - This is a catch-all for server-side failures, so root cause analysis requires log inspection ```json [4, "msg-003", "InternalError", "Database connection pool exhausted", {"timestamp": "2025-02-08T14:30:00Z"}] ``` ### ProtocolError **Description:** The payload does not conform to the OCPP protocol specification. **Common Causes:** - Sending a CALLRESULT with the wrong payload structure for the action - Message ID format violations - Sending a response to a message ID that was never sent - Incorrect message type identifier (e.g., using `2` instead of `3` for a response) - Violating the OCPP requirement that only one CALL can be pending per direction **How to Fix:** - Validate all messages against the OCPP JSON schema before sending - Ensure message IDs are correctly tracked and matched between CALL and CALLRESULT/CALLERROR - Verify that your implementation does not send a new CALL before receiving the response to the previous one - Use a protocol-level message validator in your development environment ```json [4, "msg-004", "ProtocolError", "Received CALLRESULT for unknown messageId", {"receivedMessageId": "unknown-123"}] ``` ### SecurityError **Description:** A security-related issue prevented processing the request. **Common Causes:** - Invalid or expired TLS client certificate - HTTP Basic Auth credentials rejected - Charge point identity does not match the certificate's Common Name - Attempting to perform an action that requires higher security profile authorization - Tampered message detected (in implementations using message signing) **How to Fix:** - Verify TLS certificate validity, chain completeness, and expiration dates - Confirm HTTP Basic Auth credentials match the CPMS configuration - Ensure the charge point's identity string matches across all security layers - Check that the security profile configured on the charger matches the CPMS expectations - Review certificate provisioning and rotation processes ```json [4, "msg-005", "SecurityError", "Client certificate CN does not match charge point identity", {"expected": "CP001", "received": "CP002"}] ``` ### FormationViolation **Description:** The payload is syntactically incorrect -- it is not valid JSON, or the JSON structure does not match the expected message format. **Common Causes:** - Malformed JSON (missing brackets, trailing commas, unescaped characters) - Sending a string where the protocol expects a JSON array - Incorrect encoding (the payload must be UTF-8) - Truncated messages due to WebSocket framing issues - Buffer overflow causing partial message transmission **How to Fix:** - Validate JSON syntax before sending any OCPP message - Ensure your WebSocket library correctly handles message framing and does not split messages - Use a JSON linter in your CI/CD pipeline to catch formation errors in test payloads - Check character encoding settings on both sides ```json [4, "msg-006", "FormationViolation", "Payload is not valid JSON", {"receivedPayload": "{malformed..."}] ``` ### PropertyConstraintViolation **Description:** A property value in the payload violates a defined constraint (e.g., string length, numeric range, enum value). **Common Causes:** - `idTag` exceeding the 20-character maximum length defined in the [OCPP 1.6 specification](https://openchargealliance.org/protocols/open-charge-point-protocol/) - Negative value for `meterValue` or `transactionId` - Enum value not in the allowed set (e.g., sending "Active" instead of "Charging" for ChargePointStatus) - Timestamp not in ISO 8601 format - String value exceeding `maxLength` defined in the OCPP JSON schema **How to Fix:** - Validate all property values against the OCPP JSON schema constraints before sending - Pay particular attention to string length limits, which vary by field - Use the exact enum values specified in the OCPP specification (case-sensitive) - Ensure numeric values fall within the defined ranges ```json [4, "msg-007", "PropertyConstraintViolation", "idTag exceeds maximum length of 20 characters", {"property": "idTag", "maxLength": 20, "actualLength": 25}] ``` ### OccurrenceConstraintViolation **Description:** A required property is missing from the payload, or a property that should appear only once appears multiple times. **Common Causes:** - Omitting required fields like `chargePointVendor` in `BootNotification` - Missing `connectorId` in `StatusNotification` - Omitting `idTag` in `StartTransaction` - Required nested objects not included (e.g., missing `chargingSchedule` in a `ChargingProfile`) **How to Fix:** - Cross-reference your message payloads against the OCPP specification for required vs optional fields - Implement schema validation that checks required field presence before sending - Be aware that required fields differ between OCPP 1.6 and 2.0.1 for the same action - Check for conditional requirements (fields that are required only when another field has a specific value) ```json [4, "msg-008", "OccurrenceConstraintViolation", "Required property 'chargePointVendor' is missing", {"action": "BootNotification", "missingProperty": "chargePointVendor"}] ``` ### TypeConstraintViolation **Description:** A property has the wrong data type (e.g., a string where an integer is expected). **Common Causes:** - Sending `connectorId` as a string `"1"` instead of integer `1` - Sending `meterValue` as a string instead of a number - Boolean values sent as strings (`"true"` instead of `true`) - Sending an integer where the schema expects a decimal number - Date/time values not formatted as strings **How to Fix:** - Ensure JSON serialization preserves correct types (a common issue in dynamically typed languages) - Validate payloads against the JSON schema with strict type checking - Be especially careful with languages that auto-convert between strings and numbers - Test with a schema validator that catches type mismatches ```json [4, "msg-009", "TypeConstraintViolation", "Property 'connectorId' must be integer, received string", {"property": "connectorId", "expectedType": "integer", "receivedType": "string"}] ``` ### GenericError **Description:** A catch-all error code for any error that does not fit the other categories. **Common Causes:** - Timeout waiting for a downstream system response - Rate limiting or throttling - Temporary resource contention - Implementation-specific errors that have no matching standard code - Edge cases not covered by the OCPP specification **How to Fix:** - Read the `errorDescription` carefully -- it is the primary source of information for GenericError - Check the `errorDetails` object for implementation-specific context - Contact the CPMS or charger vendor if the error description is unclear - Implement retry logic, as GenericError often indicates transient conditions ```json [4, "msg-010", "GenericError", "Request timed out waiting for authorization service", {"timeoutMs": 5000}] ``` ## Error Code Summary Table | Error Code | Severity | Retryable | Typical Source | |-----------|----------|-----------|---------------| | **NotImplemented** | High | No | Version mismatch, wrong action name | | **NotSupported** | Medium | No | Optional feature not available | | **InternalError** | High | Yes | Server-side failure | | **ProtocolError** | High | No | Message format violation | | **SecurityError** | High | No | Authentication/authorization failure | | **FormationViolation** | High | No | Invalid JSON syntax | | **PropertyConstraintViolation** | Medium | No | Invalid field value | | **OccurrenceConstraintViolation** | Medium | No | Missing required field | | **TypeConstraintViolation** | Medium | No | Wrong data type | | **GenericError** | Varies | Maybe | Catch-all for unclassified errors | ## How Do You Troubleshoot Common OCPP Errors? ### Charger Will Not Connect **Symptoms:** WebSocket connection fails or immediately closes after handshake. **Diagnostic Steps:** 1. Verify the CPMS WebSocket URL is correct, including the charge point identity in the path 2. Check that the OCPP subprotocol header is present and matches a version the CPMS supports 3. Confirm TLS certificates are valid if using WSS (check expiration, chain, and CN) 4. Ensure the CPMS is configured to accept the charge point's identity 5. Check firewall rules and load balancer configuration for WebSocket support 6. Verify that no other charge point is connected with the same identity ### Authorization Fails **Symptoms:** `Authorize` requests return `Invalid` or `Blocked` status, or trigger CALLERROR. **Diagnostic Steps:** 1. Verify the `idTag` is registered in the CPMS and is in `Accepted` status 2. Check `idTag` format and length (max 20 characters in OCPP 1.6) 3. Confirm the authorization cache (Local Auth List) is synchronized between charger and CPMS 4. Check if the parent `idTag` group is blocked or expired 5. Verify the authorization service is responsive (InternalError in the response indicates a backend failure) ### Transactions Stuck in Started State **Symptoms:** Transactions never receive a `StopTransaction` and remain open indefinitely. **Diagnostic Steps:** 1. Check if the charger disconnected during a transaction (WebSocket connection dropped) 2. Verify the charger is sending `StopTransaction` when the cable is unplugged or session times out 3. Look for `InternalError` responses to `StopTransaction` that may prevent the CPMS from processing the stop 4. Check for `transactionId` mismatches between `StartTransaction` response and subsequent `StopTransaction` 5. Implement transaction timeout logic on the CPMS side as a safety net ### Meter Values Missing or Incorrect **Symptoms:** Charging sessions show zero energy, or meter values have gaps or unrealistic values. **Diagnostic Steps:** 1. Verify `MeterValues` clock-aligned interval is configured on the charger 2. Check that the CPMS is correctly parsing the `sampledValue` array and its nested structure 3. Confirm `measurand` values match what you expect (Energy.Active.Import.Register for cumulative energy) 4. Check for timezone issues -- meter value timestamps should be in UTC 5. Verify that `MeterValues` messages are not being dropped due to WebSocket disconnections ## How Do You Debug OCPP Errors? ### WebSocket Inspection Use browser developer tools, `wscat`, or dedicated WebSocket clients to monitor raw OCPP messages. Capture the full message exchange including WebSocket handshake headers, subprotocol negotiation, and all CALL/CALLRESULT/CALLERROR frames. ### Message Logging Implement structured logging for every OCPP message with: - Timestamp (millisecond precision) - Direction (charger-to-CPMS or CPMS-to-charger) - Message type (CALL, CALLRESULT, CALLERROR) - Message ID - Action name - Full payload (redact sensitive fields like passwords) - Processing duration ### Timeout Analysis OCPP does not define a standard timeout for CALL responses, so the value is left to each implementation. Track response times for every message type to identify: - Slow actions that may indicate backend performance issues - Timeouts that cause the sender to assume failure and retry - Cascading timeouts from downstream service dependencies ## How Does OCPPLab Help Debug OCPP Errors? Reproducing OCPP errors with physical chargers is slow and limited. You cannot easily force a charger to send malformed JSON, trigger specific error codes, or reproduce timing-sensitive race conditions — which is why a dedicated [OCPP testing workflow](/blog/ocpp-testing-guide) matters. **OCPPLab** provides complete control over OCPP message flows for systematic error debugging: - **Full Message Inspection**: View every OCPP message with timestamps, raw JSON payloads, and decoded field values. Identify exactly where in a message exchange an error occurs. - **Error Injection**: Send specific CALLERROR responses to test how your CPMS handles each error code. Verify retry logic, fallback behavior, and error reporting. - **Malformed Message Testing**: Send messages with missing fields, wrong types, invalid JSON, or constraint violations to validate your CPMS error handling covers all edge cases. - **Scenario Replay**: Capture a problematic message sequence from production logs and replay it through OCPPLab to reproduce and diagnose the issue in a controlled environment. - **Concurrent Error Simulation**: Test how your CPMS behaves when multiple chargers simultaneously encounter errors, revealing race conditions and resource exhaustion issues. ## Frequently Asked Questions ### Are OCPP error codes the same in 1.6 and 2.0.1? The error codes themselves are identical between OCPP 1.6 and 2.0.1. Both versions use the same CALLERROR format and the same set of error code strings. However, 2.0.1 has additional actions and different payload schemas, so the specific constraint violations you encounter will differ. ### Should my CPMS retry after receiving a CALLERROR? It depends on the error code. `InternalError` and `GenericError` are often transient and worth retrying with exponential backoff. `NotImplemented`, `NotSupported`, `FormationViolation`, and constraint violations indicate permanent problems that retrying will not resolve. Always check the `errorDescription` for hints about whether the condition is temporary. ### How do I handle errors in production? Implement a layered approach: log every CALLERROR with full context, alert on elevated error rates, and build dashboards that track error codes by charger model and firmware version. Many production issues are firmware-specific, so correlating errors with charger metadata helps identify the root cause quickly. ### What happens if neither side sends a response? If a CALL receives no CALLRESULT or CALLERROR within the timeout period, the sender should consider the request failed. The OCPP specification does not define a specific timeout value, so it is left to each implementation. After a timeout, the sender may retry the request or close the connection and reconnect. ### Can I define custom error codes? No. The OCPP specification defines a fixed set of error codes, and both parties must use only these. If you need to communicate additional error context, use the `errorDescription` string and the `errorDetails` JSON object, which can contain any structured data you need. --- ## How to Build a CPMS: Complete Architecture Guide Source: https://ocpplab.com/blog/how-to-build-a-csms Build a production CPMS from scratch: WebSocket servers, OCPP message routing, authorization, smart charging, OCPI roaming, and scaling 6 core components. **Quick answer:** Building a CPMS means engineering a WebSocket server, OCPP message router, device registry, authorization service, transaction engine, billing, smart charging, and OCPI gateway. Implement OCPP step by step, starting with connection management, then scale connections and meter-value storage. Build it when charging is your core product, typically once you operate at large fleet scale. Building a [**CSMS (Charging Station Management System)**](/blog/what-is-csms) — often called a CPMS (Charge Point Management System) in industry copy — from scratch is a significant engineering undertaking. It requires deep understanding of the [OCPP protocol](/blog/what-is-ocpp) -- maintained by the [Open Charge Alliance](https://openchargealliance.org/protocols/open-charge-point-protocol/) -- [WebSocket infrastructure](/blog/ocpp-websocket-guide), real-time data processing, and the operational realities of EV charging networks. But for companies where charging is a core product differentiator, building your own CPMS provides unmatched control over features, integrations, and competitive advantage. This guide walks through the architecture, technology choices, implementation steps, and scaling considerations for building a production-grade CPMS. ## Why Build a CPMS Instead of Buying One? Building your own CPMS makes sense in specific circumstances. It does not make sense for everyone. ### Build When: - Charging is your primary product, not a supporting feature - You need deep integration with proprietary systems (custom billing, fleet management, energy trading) - Your business model requires features that no existing CPMS provides - You plan to operate at a scale where per-charger licensing costs exceed engineering investment - You need full control over data, security, and compliance ### Buy When: - Charging supplements your core business (hospitality, retail, real estate) - You need to deploy within weeks, not months - Your team lacks OCPP protocol and WebSocket infrastructure expertise - You are managing fewer than 1,000 chargers The break-even point varies widely. Most companies find that building becomes cost-effective only at large fleet sizes, once recurring per-charger licensing costs outweigh the upfront engineering investment -- the exact threshold depends on commercial CPMS pricing and the customization you need. ## What Does a CPMS Architecture Look Like? A production CPMS consists of several interconnected components. Each serves a distinct function, and the interfaces between them determine your system's reliability and extensibility. ### Core Components | Component | Responsibility | Key Requirements | |-----------|---------------|-----------------| | **WebSocket Server** | Manage persistent connections with charge points | High concurrency, low latency, connection state tracking | | **Message Router** | Parse OCPP messages and dispatch to handlers | Protocol version awareness, message validation, handler registry | | **Device Registry** | Track charge points, connectors, and their state | Real-time status, configuration storage, firmware tracking | | **Authorization Service** | Validate driver credentials (RFID, tokens, certificates) | Low latency (<200ms), local auth list management, group authorization | | **Transaction Engine** | Manage charging session lifecycle | Idempotent operations, meter value aggregation, billing event generation | | **Billing Engine** | Calculate costs and process payments | Tariff management, CDR generation, payment gateway integration | | **Smart Charging Engine** | Compute and distribute charging profiles | Real-time optimization, grid constraint awareness, profile stacking | | **OCPI Gateway** | Enable roaming with external networks | OCPI 2.1.1/2.2.1 compliance, partner credential management, CDR exchange | | **Monitoring and Alerting** | Track system health and charger status | Dashboards, anomaly detection, incident notification | ### High-Level Architecture ``` Load Balancer (sticky sessions) | +------------+------------+ | | | WS Server WS Server WS Server | | | +-----+------+------+----+ | | Message Bus (Redis/Kafka) | | +-------+-------+-------+--------+-------+ | | | | | | Auth Txn Smart Device Billing OCPI Svc Engine Charge Registry Engine Gateway | | | | | | +-------+-------+-------+--------+-------+ | Database Layer (PostgreSQL + Redis + TimescaleDB) ``` ## Which Technologies Should You Choose? ### WebSocket Libraries The WebSocket server is the most performance-critical component. Your choice of language and library directly impacts connection capacity and message throughput. | Language | Library | Strengths | Considerations | |----------|---------|-----------|---------------| | **Node.js** | `ws` or `uWebSockets.js` | Excellent ecosystem, fast prototyping, native JSON handling | Single-threaded event loop; use clustering for CPU-bound work | | **Go** | `gorilla/websocket` or `nhooyr/websocket` | High concurrency with goroutines, low memory per connection | Smaller OCPP ecosystem; more protocol-level code to write | | **Java** | Spring WebSocket or Netty | Enterprise tooling, strong typing, mature ecosystem | Higher memory footprint per connection, more boilerplate | | **Rust** | `tokio-tungstenite` | Maximum performance, minimal memory | Steepest learning curve, smallest OCPP ecosystem | | **Python** | `websockets` or `FastAPI` | Rapid development, data science integration | Lower throughput than compiled alternatives; viable for smaller scales | For most teams, **Node.js with `ws`** or **Go with `gorilla/websocket`** offers the best balance of development speed, performance, and ecosystem support. ### Databases A CPMS has distinct data access patterns that benefit from a polyglot persistence strategy. | Data Type | Recommended Database | Reasoning | |-----------|---------------------|-----------| | **Charge points and config** | PostgreSQL | Relational data with complex queries, strong consistency | | **Transactions and CDRs** | PostgreSQL | ACID compliance for financial data, complex reporting queries | | **Active sessions** | Redis | Sub-millisecond reads for real-time authorization and session state | | **Meter values** | TimescaleDB (PostgreSQL extension) | Time-series optimized storage, automatic partitioning, compression | | **OCPP message logs** | Elasticsearch or ClickHouse | Full-text search across millions of messages, log analysis | | **Charging profiles** | Redis + PostgreSQL | Redis for active profiles (fast reads), PostgreSQL for history | Starting with PostgreSQL for everything is a valid approach for early-stage development. Introduce specialized databases as specific performance bottlenecks emerge. ## How Do You Implement OCPP Step by Step? ### Step 1: WebSocket Server Build the connection management layer first. This is the foundation everything else depends on. **Key requirements:** - Accept WebSocket connections with OCPP subprotocol negotiation (`ocpp1.6`, `ocpp2.0.1`) - Extract charge point identity from the URL path (e.g., `/ocpp/CP001`) - Maintain a connection registry mapping charge point IDs to active WebSocket connections - Implement WebSocket Ping/Pong for connection health monitoring - Handle disconnection detection and cleanup ``` Connection URL pattern: wss://your-CPMS.com/ocpp/{chargePointId} Subprotocol negotiation: Client requests: ocpp1.6, ocpp2.0.1 Server selects: ocpp1.6 (or whichever version to use) ``` ### Step 2: BootNotification Handling `BootNotification` is the first OCPP message every charger sends after connecting. Your handler must: 1. Parse the charge point vendor, model, serial number, and firmware version 2. Decide whether to accept, reject, or set the charger to pending status 3. Return the current time (chargers use this for clock synchronization) and heartbeat interval 4. Register or update the charge point in the device registry 5. Trigger any pending configuration changes or firmware updates for this charger Accept unknown chargers in development; require pre-registration in production. The `Pending` status is useful for chargers that need manual approval or additional configuration before going live. ### Step 3: Authorization Every charging session begins with authorization. Build the authorization service to handle multiple methods: - **RFID tags**: Look up `idTag` in the database, check expiry and group membership - **Remote start**: The CPMS initiates charging via `RemoteStartTransaction` (driver uses an app) - **Local Auth List**: Maintain a cached list of authorized tags on the charger for offline operation - **Plug and Charge**: [ISO 15118](https://www.iso.org/standard/55366.html) certificate-based authorization (OCPP 2.0.1) -- see our [ISO 15118 Plug and Charge guide](/blog/iso-15118-plug-and-charge) for details Authorization latency directly impacts driver experience. Target sub-200ms response times. Use Redis caching for frequently used tags and implement the Local Authorization List for resilience during network outages. ### Step 4: Transaction Management Transactions are the core business object of a CPMS. Handle them with the reliability they demand. **Transaction lifecycle (OCPP 1.6):** 1. Charger sends `StartTransaction` with `connectorId`, `idTag`, `meterStart`, and `timestamp` 2. CPMS validates authorization, creates transaction record, returns `transactionId` 3. Charger sends periodic `MeterValues` with energy readings, power measurements, and SoC 4. Charger sends `StopTransaction` with `meterStop`, `timestamp`, and stop reason 5. CPMS finalizes transaction, calculates cost, generates billing record **Critical implementation details:** - `transactionId` assignment must be unique and sequential - Handle duplicate `StartTransaction` messages idempotently (network retries) - Process `MeterValues` asynchronously to avoid blocking the WebSocket handler - Implement transaction recovery for sessions interrupted by disconnection - Store raw meter values alongside computed totals for audit purposes ### Step 5: Smart Charging [Smart charging](/blog/smart-charging-explained) adds real-time power management to your CPMS. Start with basic load balancing and iterate toward advanced optimization. **Implementation progression:** 1. **Static load balancing**: Set a fixed OCPP 1.6 `ChargePointMaxProfile` or OCPP 2.0.1 `ChargingStationMaxProfile` per site that divides capacity equally 2. **Dynamic load balancing**: Integrate with smart meters to adjust profiles based on real-time site consumption 3. **Priority-based allocation**: Factor in driver priority, departure time, and SoC to optimize distribution 4. **Peak shaving**: Monitor demand charges and throttle charging during peak windows 5. **Demand response**: Integrate grid operator signals for external constraint management Charging profiles use a stack-level priority system. Higher stack levels override lower ones. Ensure your implementation correctly composites overlapping profiles, which is one of the most error-prone areas of OCPP smart charging. ### Step 6: OCPI Integration [OCPI (Open Charge Point Interface)](/blog/what-is-ocpi), maintained by the [EVRoaming Foundation](https://evroaming.org/ocpi/), enables roaming -- allowing drivers from other networks to use your chargers and vice versa. **Core OCPI modules to implement:** | Module | Purpose | |--------|---------| | **Locations** | Publish your charge point locations, capabilities, and real-time status | | **Sessions** | Share active charging session data with the roaming partner | | **CDRs** | Exchange Charge Detail Records for billing reconciliation | | **Tariffs** | Publish pricing information for roaming drivers | | **Tokens** | Exchange driver authorization tokens between networks | | **Commands** | Allow remote start/stop from partner networks | OCPI is a REST API (not WebSocket), so it integrates as a separate service alongside your OCPP-facing infrastructure. At minimum, implement Credentials (mandatory for all OCPI connections), Locations, Tokens, Sessions, and CDRs for a functional roaming connection. You cannot do roaming with just Locations and CDRs — Tokens are required for authorization exchange, and Sessions for real-time tracking. ## How Do You Scale a CPMS? ### WebSocket Connection Scaling Each WebSocket connection consumes memory, and the exact per-connection footprint depends heavily on your language and library choices. Across tens of thousands of chargers, connection state alone adds up to a meaningful memory budget you need to plan for. **Horizontal scaling strategy:** - Deploy multiple WebSocket server instances behind a load balancer - Use sticky sessions (source IP or cookie-based) so each charger always connects to the same instance - Implement a shared session store (Redis) so any instance can handle CPMS-initiated commands - When a charge point reconnects, it may hit a different instance; design for this ### Database Scaling **MeterValues** are the highest-volume data in a CPMS. A single charger sending frequent meter values generates hundreds of thousands of rows per year, so a fleet of tens of thousands of chargers can produce billions of rows annually. **Scaling approaches:** - Use TimescaleDB for automatic time-based partitioning and compression - Implement data retention policies (raw values for 90 days, aggregated values for 7 years) - Separate read and write workloads with read replicas - Partition transaction tables by date range - Archive completed transactions to cold storage after billing reconciliation ### Message Throughput A production CPMS must handle bursts of simultaneous messages. Common burst patterns: - **Morning peak**: Hundreds of chargers sending `StatusNotification` as drivers arrive at work - **CPMS restart**: All connected chargers send `BootNotification` simultaneously after reconnection - **Firmware update**: Mass `FirmwareStatusNotification` messages during a fleet-wide update Use a message queue (Redis Streams, Apache Kafka, or RabbitMQ) between the WebSocket layer and message handlers to absorb these bursts without dropping messages or overloading downstream services. ## How OCPPLab Accelerates CPMS Development Building a CPMS without simulated chargers means you cannot test until you have physical hardware. This creates a painful feedback loop: code for days, deploy, connect a charger, discover a bug, repeat. **OCPPLab** eliminates this bottleneck by providing virtual charge points that behave like real chargers throughout your entire development cycle: - **Develop against realistic behavior**: Connect virtual chargers to your CPMS from day one. Test BootNotification handling before you write transaction logic. - **Validate every message flow**: Exercise all OCPP message types including edge cases (offline authorization, partial meter values, interrupted transactions) without waiting for specific charger hardware. - **Load test early**: Spin up 1,000 virtual chargers to find connection management bugs, database bottlenecks, and memory leaks before they surface in production. - **Test smart charging**: Simulate multiple EVs with different battery levels, power demands, and departure times to validate your load balancing algorithms produce correct charging profiles. - **Regression testing**: Build automated test suites that run virtual chargers through critical scenarios on every deploy, catching OCPP protocol regressions before they reach production. - **Multi-version testing**: Test against both OCPP 1.6 and 2.0.1 charger behavior simultaneously, ensuring your dual-version CPMS handles protocol differences correctly. Teams using OCPPLab report cutting their CPMS development cycle by months because they can test continuously rather than waiting for hardware availability. ## Frequently Asked Questions ### How long does it take to build a CPMS? A minimum viable CPMS supporting BootNotification, Authorization, and basic transaction management takes a few months for a small team of two to three engineers. A production-grade CPMS with smart charging, OCPI roaming, billing, and monitoring typically takes considerably longer -- on the order of a year or more. Ongoing maintenance, OCPP compliance updates, and feature development are continuous after launch. ### What team do I need? At minimum: 1-2 backend engineers with WebSocket and real-time systems experience, 1 engineer with OCPP protocol expertise (or willingness to deeply study the specification), and 1 DevOps/infrastructure engineer for deployment and monitoring. For a full-featured CPMS, add frontend engineers for the operator dashboard, a data engineer for analytics, and QA engineers for protocol compliance testing. ### Should I support OCPP 1.6 and 2.0.1? Yes. OCPP 1.6 is still the most widely deployed version, and many chargers in the field will run 1.6 for years. OCPP 2.0.1 is required for new installations in many markets and provides critical features (improved transaction model, device management, ISO 15118 integration). Build your message router to handle both versions from the start, with version-specific message handlers that share common business logic. ### What is the biggest technical challenge? WebSocket connection management at scale. Maintaining tens of thousands of persistent connections, handling reconnection storms gracefully, ensuring message ordering, and routing CPMS-initiated commands to the correct server instance are all non-trivial engineering problems. Most teams underestimate this and focus too early on business logic. ### Can I use an existing OCPP library instead of building from scratch? Absolutely. Libraries like `ocpp` (Python), `node-ocpp` (Node.js), and various Java OCPP libraries handle protocol-level concerns (message parsing, validation, routing) so you can focus on business logic. Evaluate libraries for protocol completeness, maintenance activity, and community size before committing. ### How do I handle charger firmware differences? Different charger manufacturers interpret the OCPP specification differently. Some send optional fields, others omit them. Some use slightly different enum values or timestamp formats. Build your message handlers defensively: validate but accept variations, log discrepancies, and maintain a charger compatibility matrix. Testing against multiple virtual charger configurations in OCPPLab helps identify these differences before production deployment. --- ## OCPP Emulator: A Complete Guide to Virtual Testing Source: https://ocpplab.com/blog/introducing-ocpp-emulator OCPPLab is an OCPP emulator for testing EV charging software without hardware, covering OCPP 1.6, 2.0.1, and OCPI so teams can validate before deployment. We're excited to unveil **OCPPLab**, an innovative testing platform designed to revolutionize EV charging infrastructure development and deployment. ## What Challenge Does OCPPLab Address? In today's rapidly growing EV charging ecosystem, developers face several critical hurdles: - Complex [OCPP protocol](https://openchargealliance.org/protocols/open-charge-point-protocol/) testing and validation - Time-consuming hardware-dependent testing cycles - Difficulty in simulating diverse charging scenarios - Limited access to multiple charging station models OCPPLab tackles these challenges head-on, offering a comprehensive virtual testing environment that accelerates development and ensures robust charging infrastructure. ## Our Mission 1. **Accelerate Development**: Test OCPP implementations without physical hardware dependencies 2. **Ensure Reliability**: Validate your [charging management system (CPMS)](/blog/what-is-csms) with comprehensive protocol coverage 3. **Reduce Costs**: Minimize expensive hardware procurement for testing purposes 4. **Scale Testing**: Simulate large fleets of virtual charging stations simultaneously ## Core Capabilities - **Multi-Protocol Support**: Full compatibility with [OCPP 1.6](https://openchargealliance.org/protocols/open-charge-point-protocol/), [OCPP 2.0.1](/blog/ocpp-1-6-vs-2-0-1), and [OCPI](https://evroaming.org/ocpi/) standards - **Virtual Charge Points**: Simulate any charging station model with realistic behavior patterns - **Load Testing**: Test [system scalability under load](/use-cases/ocpp-load-testing) with high volumes of concurrent charging sessions - **Protocol Validation**: Comprehensive message validation and compliance checking - **Real-time Monitoring**: Live dashboard for tracking emulated charging station activity - **Custom Scenarios**: Create complex charging workflows and edge case testing ## Why Does OCPPLab Stand Out? By removing hardware dependencies, OCPPLab is designed to shorten QA cycles and reduce the cost of maintaining testing infrastructure. Our emulation platform isn't just a tool; it's your competitive advantage. For a deeper look at the tradeoffs, see our comparison of [virtual versus physical testing](/blog/virtual-vs-physical-testing). Here's how we compare: | Feature | OCPPLab | Physical Testing | Other Emulators | | -------------------------- | ------------- | ---------------- | ---------------- | | Multi-Vendor Support | Yes | No | Partial | | Scalable Load Testing | Yes | No | Partial | | Cost-Effective Testing | Yes | No | Yes | | Protocol Compliance | Yes | Yes | Partial | | Rapid Iteration | Yes | No | Yes | ## How Do You Get Started with OCPPLab? Embarking on comprehensive [OCPP testing](/blog/ocpp-testing-guide) is seamless: 1. **Setup**: Deploy OCPPLab in your environment 2. **Configure**: Define your charging station models and protocols 3. **Test**: Run comprehensive testing scenarios 4. **Validate**: Ensure full OCPP compliance before production 5. **Scale**: Test with large fleets of virtual charging points --- ## How to Test OCPP Protocols Effectively: Complete Guide Source: https://ocpplab.com/blog/ocpp-testing-guide Learn to test OCPP protocols effectively with compliance, functional, and load testing across 4 phases, using virtual emulation to skip costly charger hardware. **Quick answer:** Effective OCPP testing combines protocol compliance validation, functional testing, and load/performance testing, using virtual testing environments to emulate charge points without expensive hardware. Design test scenarios for happy paths, error handling, edge cases, and security, then integrate testing into your CI/CD pipeline and track compliance, coverage, and defect-detection metrics to build confidence before deployment. Testing OCPP protocols effectively is crucial for building reliable EV charging infrastructure. Here's your complete guide to **mastering OCPP testing** with modern emulation techniques. ## What Are the Biggest OCPP Testing Challenges? [OCPP (Open Charge Point Protocol)](https://openchargealliance.org/protocols/open-charge-point-protocol/) testing presents unique challenges in the EV charging ecosystem: - **Protocol Complexity**: [OCPP 1.6 and 2.0.1](/blog/ocpp-1-6-vs-2-0-1) define dozens of distinct message types between them, each with its own required and optional fields - **Hardware Dependencies**: Traditional testing requires expensive physical chargers - **Scalability Issues**: Testing with multiple charging stations simultaneously - **Scenario Coverage**: Validating edge cases and error conditions Effective OCPP testing requires a strategic approach that addresses each of these challenges systematically. ## Which OCPP Testing Strategies Are Essential? ### 1. **Protocol Compliance Validation** Ensure your [CPMS](/blog/what-is-csms) correctly implements OCPP standards. The Open Charge Alliance's own [Compliance Test Tool (OCTT)](https://openchargealliance.org/test-tool/) is the reference benchmark here: - Message format validation - Required vs optional field handling - Error response mechanisms - [Security profile](/blog/ocpp-security-profiles-explained) compliance ### 2. **Functional Testing** Validate core charging station operations: - Remote start/stop transactions - Firmware update procedures - Configuration parameter management - Reservation handling ### 3. **Load and Performance Testing** Test system scalability and performance: - Concurrent connection handling - Message throughput validation - Memory and CPU usage monitoring - Database performance under load ## Best Practices for OCPP Testing ### Virtual Testing Environment Choosing between [virtual and physical testing](/blog/virtual-vs-physical-testing) shapes how quickly you can iterate. **Benefits of Virtual Testing:** - **Cost Effective**: No hardware procurement needed - **Scalable**: Test thousands of charge points simultaneously - **Repeatable**: Consistent test conditions every time - **Fast Iteration**: Rapid test-debug cycles ### Test Scenario Design Create comprehensive test scenarios covering: 1. **Happy Path Testing**: Normal charging workflows 2. **Error Handling**: Network failures, invalid messages 3. **Edge Cases**: Concurrent transactions, power outages 4. **Security Testing**: Certificate validation and secure communication, including [ISO 15118](https://www.iso.org/standard/69113.html) Plug & Charge flows where relevant ## What Does a Real-World OCPP Testing Framework Look Like? A well-designed OCPP testing framework can significantly reduce deployment issues and catch problems that would be expensive to fix in production. Pairing the right [OCPP testing tools](/blog/best-ocpp-testing-tools-compared) with a clear pipeline tends to make the difference. ### Recommended Testing Pipeline: | Phase | Focus | Tools | Duration | |-------|-------|-------|----------| | Unit Testing | Message validation | OCPPLab | 1-2 days | | Integration Testing | End-to-end workflows | Virtual stations | 3-5 days | | Load Testing | Performance validation | Stress testing | 2-3 days | | UAT | Business scenarios | Staging environment | 1 week | ## Advanced Testing Techniques ### Automated Test Suites ```python # Example automated test def test_remote_start_transaction(): station = YacineElazrak.create_station("station_001") response = station.remote_start_transaction( connector_id=1, id_tag="RFID123456" ) assert response.status == "Accepted" ``` ### Continuous Integration Integrate OCPP testing into your CI/CD pipeline: - Automated regression testing - Performance benchmarking - Protocol compliance checks - Security vulnerability scanning ## How Do You Measure OCPP Testing Success? Track these key metrics: - **Protocol Compliance Score**: Percentage of OCPP messages correctly handled - **Test Coverage**: Percentage of OCPP features tested - **Defect Detection Rate**: Issues found in testing vs production - **Performance Benchmarks**: Response times and throughput metrics Effective OCPP testing isn't just about finding bugs—it's about building confidence in your charging infrastructure before it reaches the field. ---