Urgent.News

What's breaking now, across thousands of outlets.

Tech

Building an OCPP Backend: Lessons from Supporting OCPP 1.6J and OCPP 2.0.1 in Production

Building an OCPP backend looks simple at first. A charger opens a WebSocket connection, sends a BootNotification , the backend responds, and you're connected. Then you connect real chargers . That's where things get interesting. While building and testing Ureticy , our OCPP software platform, we've worked with real EV charging hardware using both OCPP 1.6J and OCPP 2.0.1 . The biggest lesson?…

Building an OCPP backend may seem straightforward at first glance. A charger establishes a WebSocket connection, transmits a BootNotification, and the backend replies, thus re-establishing the connection. However, this simplistic view belies the complexities that arise when deploying in a production environment. This story explores the lessons learned after supporting both OCPP 1.6J and OCPP 2.0.1 in the Ureticy OCPP software platform.

1. BootNotification is merely the starting point: While receiving a successful BootNotification is a positive sign, it only demonstrates that the initial communication is functional. Hidden issues often surface later, such as authorization, connector status, transaction handling, meter values, remote start/stop, reconnection behavior, EVSE/connector mapping, and vendor-specific behaviors. Consequently, treating a successful boot as the end of integration testing is a mistake.

2. Real chargers do not always emulate simulator behavior: Development simulators are invaluable during the initial stages of development. However, production hardware introduces additional layers of complexity. Chargers from various manufacturers can behave differently during authorization, transaction handling, or status updates. Thus, comprehensive logging and observability become crucial to facilitate remote debugging.

3. OCPP 1.6J and OCPP 2.0.1 are fundamentally different: It's a common error to consider OCPP 2.0.1 as a merely enhanced version of OCPP 1.6J. Architecturally, OCPP 2.0.1 has undergone significant changes. In OCPP 1.6J, transactions typically involve StartTransaction → MeterValues → StopTransaction. In contrast, OCPP 2.0.1 follows a TransactionEvent framework with Started → Updated → Ended. This architectural shift necessitates a rethinking of how backend systems model charging sessions.

4. Mapping EVSEs and connectors correctly is vital, particularly with OCPP 2.0.1: A common assumption is that EVSE 1 corresponds to Connector 1. However, a charging station may house multiple EVSEs and connectors. A more robust internal structure would be: Charging Station → EVSE → Connector. This distinction becomes critical when debugging issues, especially during late-night troubleshooting sessions.

5. Defensive handling of MeterValues is essential: MeterValues provide energy data, but not all chargers provide the same set of measurements, including Energy, Power, Current, Voltage, State of Charge (SoC), Temperature, etc. A production backend must not assume that every value will always be present. If a particular value is unavailable, the system should still function smoothly, displaying available data where possible.

6. RemoteStart does not equate to charging initiation: A RemoteStart request signifies the initiation of a remote command but does not guarantee that energy is already flowing. The actual charging process may unfold as follows: Remote command accepted → Authorization → Transaction creation → EV readiness → Energy flow commencement. Conversely, stopping a charging session involves additional steps, emphasizing the need for clear state distinctions in applications to avoid misinformation to customers.

7. Ensuring WebSocket reliability is paramount: EV chargers maintain long-lived connections, making network instability a significant concern. Factors such as router restarts, internet disconnections, mobile network instability, and occasional chargers reconnecting without a clean disconnection all contribute to potential connection issues. A resilient production OCPP backend must address heartbeat management, handle stale connections, manage reconnections, detect duplicate sessions, and ensure proper transaction recovery.

8. Observability is a crucial product feature: Initially, logging might appear to be an engineering task. However, once real chargers are integrated, observability transforms into a product feature. When failures occur, developers must promptly understand the charger's exact message transmission. To aid in this process, Ureticy has developed a Chrome extension for working with OCPP messages, enabling direct message analysis in the browser without uploading payloads to external servers.

9. Separating protocol logic from business logic is an essential architectural decision: Protocol handling should be distinct from business logic. The backend should understand OCPP, while the business layer focuses on the product's logic. An effective architectural approach separates the protocol layer from the normalized events, business rules, and database/API/application layers. This separation simplifies the process of accommodating future protocol versions and allows for cleaner, more maintainable codebases.

10. Don't underestimate the importance of detailed documentation: Often overlooked during development, thorough documentation is indispensable for maintaining and scaling the backend system. Clear documentation ensures that future developers can quickly understand the system's architecture, allowing for easier integration of new features and troubleshooting of existing issues.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Wednesday 7 October →