Designing a Scalable OCPP server
What is OCPP?
OCPP, short for Open Charge Point Protocol, is like the universal language of EV charging. It sets the standard for how charging stations talk to central systems, enabling functions like monitoring, management, billing, and even integration with third-party systems. This open-source protocol isn’t just a buzzword — it’s backed by a robust community of vendors and manufacturers, making it a widely adopted and trusted solution.
How OCPP Works
At its core, OCPP operates through two main components: the protocol itself and its profiles. The protocol defines the communication rules between charge points and central servers, while profiles determine what data gets exchanged. Picture this: a driver plugs in their EV at a charging station. OCPP kicks into action, transferring driver details to the central server for authentication and initiating the charging process. Simultaneously, the station communicates key data like energy usage and status back to the central system for billing and maintenance purposes.
Chargers
Chargers communicate with the OCPP or CMS server using the same OCPP protocol. They are equipped with small hardware, similar to a Raspberry Pi, where firmware code is written. This code is responsible for monitoring and transferring data about specific charging sessions to the OCPP server. Additionally, it accepts commands such as startTransaction and stopTransaction from the standard OCPP server to initiate a charging session.
Chargers also communicate with the Battery Management System (BMS) of electric vehicles (EVs) using the ISO 15118–2 digital communication protocol can see in fig 1.1, which implements various features. This protocol facilitates seamless communication between the charger and the EV’s BMS, ensuring efficient and coordinated charging processes:
- security concept including encryption, signing, key management, etc.
- robust PLC-based communications
- automatic address assigning and association
- IPv6-based communications
- compressed XML messages
- client-server approach
- safety concept including cable check, welding detection, etc
- extension concept for added-value services
Design Tradeoff
Now that we both have established some foundational concepts and are on the same page, let’s delve into the implementation aspect from a - software engineering perspective. To build an OCPP server, we need to consider various factors.
Firstly, we should brainstorm about the implementation details, such as choosing the appropriate design pattern — whether to opt for a client-server model, an event-driven architecture, or a stateless or stateful approach. Additionally, we need to decide on the programming language, protocol (e.g., HTTPS, WebRTC, WebSocket, or a queue-based implementation), and database technology. These choices will shape the robustness, scalability, and efficiency of our OCPP server.
Before diving into implementation specifics, let’s consider a scenario. To initiate a charging session, a user triggers a command from the app, which sends a request to the OCPP server. The OCPP server then establishes communication with the charger, instructing it to begin the charging session.
Client-server
Now, let’s visualize how your system might look if you opt for a client-server model:
- Start charger from user
- charger started from charger
- state of charging session from user evry 1 or 2 sec
- end of chrging from user
- session ended fron charger
Roughly 5 http connection and state of chrging session csn be varry but lets fix this for 50(anyhow you going to chrge your veichle more than 50second). Starting the charger from the user’s end, the charger begins charging from its side. The charging session’s state is updated from the user’s end every 1 or 2 seconds. When the charging is complete, the user ends the session, and the session is ended from the charger’s side as well.
However, using this model can lead to several drawbacks and overheads, especially due to the multiple HTTPS calls involved. Here are some potential issues:
Increased Cost
Each HTTPS call incurs a cost, especially if using external services or APIs. With roughly 50 HTTP connections per session, this cost can add up significantly over time.
HTTP Header Overhead and Handshaking
Each HTTP request and response involves the exchange of headers, which contain metadata about the request and response. This header overhead can become significant, especially when multiple HTTP connections are made within a short period. Additionally, establishing a new connection for each HTTP request requires the overhead of handshaking, where the client and server negotiate parameters and establish the connection. Even when the client and server remain the same, this repeated handshaking process adds to the overall latency and resource consumption, impacting the speed and efficiency of the charging process. Implementing strategies like connection pooling, persistent connections, or using protocols optimized for low overhead, such as WebSocket, can help alleviate these issues and improve performance.
Impact on Latency and Speed
Multiple HTTPS calls introduce latency and can slow down the overall charging process. This delay can be noticeable, especially in scenarios where rapid responses are required, such as managing real-time charging sessions or handling high volumes of transactions.
Complexity in Management
Managing and coordinating multiple HTTPS calls can add complexity to the system architecture. It requires robust error handling, retries, and monitoring mechanisms to ensure smooth operation and reliability.
Resource Utilization
Each HTTPS call consumes resources, including network bandwidth, server processing power, and memory. In situations with a large number of concurrent sessions, this can strain the system and impact overall performance.
To mitigate these drawbacks, optimizing the HTTPS calls, implementing caching mechanisms, reducing unnecessary data transfers, and considering alternative communication protocols or optimizations can help improve efficiency and reduce overhead.
Statefull system
In the previous model, we encountered challenges due to the repeated use of HTTP connections, which led to costly handshaking mechanisms and increased header lengths. However, let’s consider a more efficient approach using an event-driven and stateful system, leveraging the benefits of WebSocket technology.
In this optimized model, we acknowledge that our OCPP server and charger remain the same entities throughout the process. By adopting a stateful system, we can persist the connection between the client (user or charger) and the server (OCPP server). This persistence eliminates the need for frequent handshakes and reduces the overhead caused by lengthy headers.
Now, let’s talk about using
WebSocket
Duplex Mechanism
WebSocket’s duplex mechanism allows for simultaneous data transfer from both ends over a single connection. This bidirectional communication capability is crucial for real-time updates and efficient interaction between the user and the server.
Latency and Speed
By maintaining a persistent connection, WebSocket significantly reduces latency compared to traditional HTTP connections. The elimination of repeated handshaking and header overhead results in faster data transmission, enhancing the overall speed and responsiveness of the charging process.
Fewer Connections
WebSocket’s persistent nature means fewer connection establishment overheads. Unlike HTTP, where each request requires a new connection and handshake, WebSocket maintains a continuous connection, leading to fewer resources consumed and improved efficiency.
Technical Details
WebSocket operates over TCP, providing a reliable and full-duplex communication channel. It uses a lightweight protocol that minimizes overhead, making it ideal for real-time applications like EV charging management. WebSocket’s support for binary data transmission and built-in error handling further enhances its suitability for handling EV charging sessions seamlessly.
By using WebSocket within an event-driven and stateful architecture, we can optimize the communication between the charger, user, and OCPP server. This approach not only reduces overhead and latency but also ensures a smoother and more responsive charging experience.
Choosing Database
Choosing a scalable database like ScyllaDB for a real-time EV charging management system with WebSocket technology offers several advantages:
Real-Time Performance
ScyllaDB’s high-throughput and low-latency capabilities make it ideal for handling real-time data streams and rapid updates in an event-driven system.
Horizontal Scalability
ScyllaDB’s distributed architecture allows for seamless horizontal scaling by adding more nodes, ensuring the system can accommodate growing data volumes and user traffic.
Flexible Schema
With support for flexible schemas, ScyllaDB enables easy adaptation to evolving data structures and simplifies integration with WebSocket-based real-time data streams.
High Availability
ScyllaDB’s fault-tolerant design and automatic sharding ensure high availability and reliability, crucial for mission-critical applications like EV charging management.
In summary, ScyllaDB provides the performance, scalability, flexibility, and reliability needed for a modern, real-time EV charging system utilizing WebSocket technology.
System Design
Designing a Detailed System Architecture for Real-Time EV Charging Management
WebSocket Communication Layer
Implement WebSocket protocol for real-time bidirectional communication between EV chargers, users, and the OCPP server. Use WebSocket libraries and frameworks like Socket.IO for efficient WebSocket management and event handling.
ScyllaDB for Data Storage
Utilize ScyllaDB as the primary database for storing real-time charging session data, user information, and system configurations.
Redis for Scaling and Caching
Integrate Redis as a caching layer for scaling WebSocket connections and maintaining session states. Use Redis Pub/Sub for real-time notifications and event broadcasting to connected clients
Stateful API Gateway
Design a stateful API gateway using Redis to manage session states, authenticate users, and handle API requests. Utilize Redis data structures like Hashes and Sets for storing session information, user tokens, and access control lists (ACLs).
Kafka for Ultra-Scalable Event Processing
Integrate Kafka as a message broker for handling high-throughput event streams and data processing. Use Kafka topics for event-driven architecture, allowing components to publish and subscribe to relevant events.
Microservices Architecture
Design the system using a microservices architecture for modularity, scalability, and fault isolation. Create microservices for user management, charging session control, billing, monitoring, and analytics, each interacting through Kafka and Redis for data synchronization and event-driven communication.
Load Balancing and Auto-Scaling
Implement load balancing using Nginx or a similar tool to distribute WebSocket connections and API requests across multiple servers. Configure auto-scaling policies based on metrics like CPU utilization, WebSocket connection count, and API request rate to dynamically adjust resource allocation and handle traffic spikes efficiently.
Current Architecture Design
Now that we have a clear understanding of our technology, tools, and architecture, let’s simulate the entire system using a straightforward example, step by step. Imagine planning a road trip from start to finish.
Starting a Charging Session
The user initiates a charging session through the mobile app or web interface, sending a request to the OCPP server via HTTPS or WebSocket API endpoints.
OCPP Server Interaction
Upon receiving the request, the OCPP server processes the command and verifies the user’s credentials and authorization for the charging session. The OCPP server updates the charging session status in ScyllaDB, indicating that a new session is initiated and the user is authorized to charge.
WebSocket Communication
The OCPP server establishes a WebSocket connection with the designated charger identified for the session, using the persistent connection pool managed by Redis for efficient connection management. Data related to the charging session, such as start command, charging parameters, and user authentication, is sent over the established WebSocket connection to the charger.
Charger Starts the Session
The charger receives the data from the WebSocket connection and verifies the session details and authorization. Upon successful validation, the charger starts the charging session, initiating the flow of electrical power to the EV.
Session Feedback and Status Update
The charger sends real-time updates and feedback about the charging session, such as current charging rate, energy consumption, and battery status, back through the WebSocket connection to the OCPP server. The OCPP server processes and updates the session status in ScyllaDB, continuously tracking and recording session data for monitoring and analytics purposes.
Publishing to Kafka
Key events and data updates related to the charging session, such as session start, stop, charging status changes, and energy consumption milestones, are published as messages to specific Kafka topics. Kafka acts as a centralized message broker, ensuring reliable delivery of messages and providing durability and fault tolerance.
Microservices Consumption
Multiple microservices within the system architecture subscribe to relevant Kafka topics, consuming and processing the published messages. For example, a billing microservice calculates and records charging costs based on energy consumption data received from Kafka messages. Another monitoring microservice tracks charging session metrics and generates real-time alerts or notifications for system administrators or users
Yes, this was it. It was all that I understood and my approach for such a system from a software engineer’s perspective.
Now, there are a lot of ways and tools you can use for building an EV charging infrastructure system that can be more scalable and robust.
My take on the EV industry from a software point of view is that it is still very immature. Many things designed or currently being developed are mostly from a hardware or business point of view, which is good. However, at the end of the day, you’re dealing with abstract software systems, which should be the prime focus of institutions.
There are very few experts who know the system from end to end, and even fewer who want to know. There is a scarcity of good blogs and reading materials, and the ones available are often not structured.
Also, I am developing an open-source OCPP server from scratch that anyone can use and build upon. It will take time, so stay tuned to my GitHub, which you can find [here](siddharth github). You can follow me on GitHub to track my progress.