OCPP is the dominant protocol for communicating between EV charging stations and the software systems that manage them. If you have built OCPP integrations in production, you know the spec is better than what came before it, and it is also a reliable source of surprises the first few times you deploy against real hardware.

This is a collection of lessons from actual OCPP integration work — the things that bit us, the patterns that worked, and the edge cases worth knowing about before you encounter them in production.

The WebSocket connection lifecycle is not trivial

OCPP runs over WebSocket. The charging station initiates the connection to your CSMS, and the session persists for as long as the station is online. This is different from typical REST API integrations where you control when connections happen.

The first lesson from the field: your CSMS needs to handle connection instability gracefully. Charging stations lose connectivity. They reboot for firmware updates. They are installed in parking garages with poor cellular coverage. Your CSMS should maintain a map of connected chargers, detect when connections drop, and handle reconnections without dropping queued messages or losing transaction state.

Heartbeat messages (the station sends Heartbeat, CSMS responds with current timestamp) are the mechanism OCPP uses for presence detection. If you stop receiving heartbeats from a charger, it has gone offline. How long you wait before declaring a charger unreachable depends on your configured heartbeat interval — typically 30 to 60 seconds. Build your presence detection logic with the heartbeat interval in mind.

Transaction state must survive CSMS restarts

An EV charging session can last two to eight hours. Your CSMS will restart during a maintenance window at some point. When it does, you need to recover the state of every active transaction without data loss.

The minimal requirement: persist transaction state to durable storage on every state transition. Every StartTransaction, every MeterValues message, every StopTransaction should write to persistent storage before you acknowledge it to the charger. If you acknowledge the message and then lose it in memory on restart, you have a gap in your transaction history that may surface as a billing dispute.

OCPP 1.6 does not specify how the CSMS should handle incomplete transactions after a restart. We have seen approaches ranging from querying chargers for their current status on reconnect, to using the next BootNotification to trigger a transaction status reconciliation. Whatever approach you take, test it explicitly by killing your CSMS mid-transaction and verifying the recovered state.

MeterValues: the data you actually want is behind a config flag

OCPP chargers can report a range of electrical measurements during charging sessions: power in watts, energy in Wh, current per phase, voltage, SoC for the connected vehicle. The default configuration for most chargers only reports a subset of this data at a default interval (often 5 minutes).

If your application needs finer-grained energy data — for demand response dispatch, for energy cost calculation, for capacity management — you need to configure the charger's MeterValuesSampledData and MeterValueSampleInterval parameters via ChangeConfiguration messages. This is a step that teams often skip in early integration work and discover missing later when they try to build analytics features.

Worth noting: not all chargers support all meter value measurands. A charger that does not have per-phase current sensors will not report Current.Import per phase even if you request it. Querying GetConfiguration and inspecting MeterValuesSampledData gives you the set of measurands the charger actually supports.

Smart charging: the gap between spec and implementation

OCPP 1.6 defines a smart charging profile mechanism that lets your CSMS set power limits for individual charging sessions or for a charging station as a whole. This is the feature that enables demand response integration — you send a SetChargingProfile with a schedule that limits charge current during peak hours, and the charger enforces it.

The practical lesson: smart charging support is highly variable across charger manufacturers. Some vendors implement it fully and reliably. Others implement it with undocumented limitations — a maximum of one active profile at a time, no support for recurring schedules, minimum charge current that is higher than what the spec allows. Before committing to smart charging functionality in your product, test the specific charger models your customers deploy against your CSMS implementation.

Smart charging was the feature that got us the most requests and caused us the most production incidents in the first year. The spec says it works; the hardware says sometimes.

Handling firmware updates and BootNotification

Charging stations send a BootNotification message every time they come online — including after firmware updates. After a firmware update, a charger may change its behavior in ways that your integration did not anticipate: different default meter value intervals, changed error code formats, added support for optional OCPP features, or removed support for features it previously reported.

Build your CSMS to treat every BootNotification as a potential capability change. Query the charger's configuration after reconnect, compare it to the last known state, and flag significant changes for review. A charger that upgraded its firmware overnight and now behaves differently is a common source of integration bugs that are hard to reproduce in testing.

Authorization: RFID versus central authorization

OCPP supports two authorization models: local authorization (the charger checks a locally stored list of RFID tags) and central authorization (the charger sends an Authorize request to the CSMS and waits for a response before starting a session). Each has different reliability characteristics.

Local authorization is faster and works when the charger has no network connectivity, but keeping the local authorization list in sync across a fleet of chargers is a maintenance burden. Central authorization is simpler to manage but adds latency to session start and fails when the network is down.

The right model depends on your deployment context. Fleet charging in a controlled site with reliable connectivity can use central authorization. Public charging in variable network conditions benefits from local authorization with a synchronized allowlist. Most production deployments use a hybrid: central authorization with a local fallback list for when the CSMS is unreachable.

OCPP is a workable protocol for EV charging software integration. The spec is clear enough, the ecosystem is mature, and the tooling is improving. The field lessons above are not arguments against OCPP — they are the map of where to invest attention so the integration holds up when it counts.