ocpp-client 0.4.0

OCPP Client Implementation. Use this library to implement an OCPP charge point
Documentation

๐Ÿ”Œ OCPP Client

A lightweight, embedded-friendly Rust OCPP communication framework for building real charge points and CSMS integrations.

Rust License Crates.io Documentation .github/workflows/ci.yaml no_std


๐Ÿš€ Overview

OCPP Client is the communication layer of the Flowion Rust OCPP ecosystem, providing the networking and transport foundation required to build OCPP-enabled charge points and backend integrations.

The library handles the complexities of establishing and managing OCPP connections, including:

  • Connection lifecycle management
  • Transport handling
  • Message routing
  • Communication reliability

OCPP message types and protocol definitions are provided by ocpp-types, while OCPP Client focuses on the communication layer required to exchange messages between charge points and Charge Station Management Systems (CSMS).

Designed for both cloud/server environments and resource-constrained embedded systems, OCPP Client speaks WebSocket out of the box and compiles for no_std + alloc targets. An embassy-net-based transport and an STM32 board scaffold ship alongside it as experimental crates - see Supported Transports.

The library currently supports OCPP 1.6J, OCPP 2.0.1, and OCPP 2.1.


โœจ Features

  • ๐Ÿฆ€ Native Rust implementation
  • ๐Ÿ”Œ OCPP communication layer
  • โšก OCPP 1.6J support
  • ๐Ÿš€ OCPP 2.0.1 support
  • โšก OCPP 2.1 support
  • ๐ŸŒ WebSocket transport
  • ๐Ÿ”’ Secure WebSocket (WSS)
  • ๐Ÿ”‹ embassy-net transport for embedded targets (experimental)
  • ๐Ÿ”„ Connection lifecycle management
  • ๐Ÿ’“ Scheduled WebSocket keepalive with dead-peer detection
  • ๐Ÿ“จ Message routing
  • ๐Ÿงฉ Transport abstraction
  • ๐Ÿชถ Lightweight runtime
  • ๐Ÿ’พ no_std support for embedded environments
  • ๐Ÿ–ฅ๏ธ std support enabled by default for desktop and server applications

๐Ÿ”Œ Supported Protocols

Protocol Status Actions wired up
OCPP 1.6J โœ… Supported all 39
OCPP 2.0.1 โœ… Supported all 64
OCPP 2.1 โœ… Supported all 91

1.6's 39 includes the eleven actions from the security whitepaper (SignCertificate, GetLog, SignedUpdateFirmware and friends), wired up in 0.4.0 when ocpp-types first defined them.

Every action defined by ocpp-types for each version has a send_*/on_* method - tests/action_coverage.rs fails the build otherwise, so the table can't drift. If a method you expect is missing, check CHANGELOG.md before filing an issue: five actions were only wired up in 0.2.1, so a 0.2.0 build is missing SecurityEventNotification (2.0.1) and TriggerMessage, SetDisplayMessage, GetDERControl, SetDERControl, UpdateDynamicSchedule (2.1).


๐ŸŒ Supported Transports

Transport Status
WebSocket โœ… Supported
Secure WebSocket (WSS), incl. mutual TLS โœ… Supported
embassy-net (embedded, no_std + alloc) ๐Ÿงช Experimental

The embedded transport (crates/ocpp-transport-embassy-net) and the NUCLEO-H723ZG firmware scaffold (crates/ocpp-board-stm32h723-nucleo) compile and fully link against the real thumbv7em-none-eabihf target in CI, but neither has been run against real hardware or a real CSMS, and the embedded transport has no TLS. Treat them as a starting point for a board bring-up rather than a supported deployment path. Each crate's README states its exact status.


โš™๏ธ Feature Flags

OCPP Client supports both standard Rust environments and embedded systems.

By default, the std feature is enabled:

[dependencies]
ocpp-client = "0.x"

For embedded targets or no_std environments:

[dependencies]
ocpp-client = { version = "0.x", default-features = false }

This lets the same OCPP communication core compile for resource-constrained devices as well as server-side applications. Embedded users supply their own Executor/Timer implementations (e.g. backed by embassy-executor/embassy-time) and a critical-section backend for their target.

The optional chrono feature adds From/Into between ocpp_types::OcppTimestamp - the type every dateTime field uses - and chrono::DateTime, for applications that already keep time in chrono. It is interop only; chrono never reaches the wire.


๐Ÿ—๏ธ Architecture

OCPP Client separates protocol definitions from communication.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚          Your Application                  โ”‚
โ”‚          Charge Point / CSMS Logic         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚
                       โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              ocpp-charge-point             โ”‚
โ”‚                                            โ”‚
โ”‚  Complete charge point firmware framework  โ”‚
โ”‚  Add hardware bindings and deploy          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚
                       โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              ocpp-client                   โ”‚
โ”‚                                            โ”‚
โ”‚  OCPP communication runtime                โ”‚
โ”‚  Transport abstraction                     โ”‚
โ”‚  WebSocket / embedded transports           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚
                       โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚               ocpp-types                   โ”‚
โ”‚                                            โ”‚
โ”‚  OCPP message types                        โ”‚
โ”‚  Protocol models                            โ”‚
โ”‚  Serialization                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐ŸŒ Flowion OCPP Ecosystem

OCPP Client is designed as a modular building block within the Flowion Rust OCPP ecosystem.

Each project has a focused responsibility, allowing developers to choose the right level of abstraction for their application.


๐Ÿ“ฆ ocpp-types

OCPP protocol definitions and data models

ocpp-types provides the foundation for working with OCPP messages in Rust.

It contains:

  • OCPP message types
  • Protocol models
  • Serialization and deserialization
  • Version-specific protocol definitions

OCPP Client builds on top of ocpp-types to provide communication capabilities.


๐Ÿ”Œ ocpp-client

OCPP communication and transport layer

This repository provides the runtime required to connect OCPP-enabled systems.

It handles:

  • Connection management
  • Transport abstraction
  • Message routing
  • WebSocket communication
  • Embedded-compatible transports
  • no_std environments

It is designed to run in both:

  • ๐Ÿ–ฅ๏ธ Server environments
  • ๐Ÿ”‹ Embedded charge point environments

โšก ocpp-charge-point

Complete charge point firmware framework

ocpp-charge-point provides a complete framework for building OCPP-enabled charge point firmware.

The goal is to make developing custom charging hardware as simple as implementing the required hardware bindings.

Developers provide hardware-specific implementations such as:

  • GPIO control
  • Contactor control
  • Metering interfaces
  • Connector handling
  • LEDs and user interfaces
  • Hardware drivers

while the framework handles:

  • Charge point state management
  • OCPP communication
  • Charging workflows
  • Backend communication
  • Protocol integration

This allows manufacturers and developers to build custom OCPP-compatible chargers without implementing the complete protocol stack from scratch.


๐ŸŽฏ Use Cases

OCPP Client can be used for:

  • ๐Ÿš— Building EV charge point firmware
  • ๐Ÿญ Developing OCPP-enabled hardware
  • ๐Ÿ–ฅ๏ธ Building CSMS integrations
  • ๐Ÿงช Testing OCPP implementations
  • ๐Ÿ”‹ Connecting embedded devices to charging platforms
  • โšก Creating custom charging solutions
  • ๐Ÿค– Automated integration testing

๐Ÿ“ฆ Installation

Add the dependency to your Cargo.toml:

[dependencies]
ocpp-client = "0.x"

๐Ÿš€ Quick Example

use ocpp_client::connect_1_6;
use ocpp_client::ocpp_types::v16::HeartbeatRequest;

#[tokio::main]
async fn main() {
    // `None` takes the defaults: 5s request timeout, automatic reconnect, and keepalive
    // pinging every 60s.
    let client = connect_1_6("wss://example.com/ocpp", None).await.unwrap();

    let response = client.send_heartbeat(HeartbeatRequest {}).await.unwrap();
    println!("CSMS time: {}", response.current_time);
}

Use connect_2_0_1/connect_2_1 for those versions, or connect to negotiate whichever version the server picks.

Vendor extensions (customData)

2.0.1 and 2.1 hang an optional customData object on nearly every message. The send_*/on_* methods use the specification's own shape - a bare vendorId - which is all most deployments need. To carry your own, name the type on the action marker and go through call/on:

#[derive(serde::Serialize, serde::Deserialize)]
struct AcmeExtension {
    #[serde(rename = "vendorId")]
    vendor_id: String,
    #[serde(rename = "siteId")]
    site_id: u32,
}

let response = client.call::<Reset<AcmeExtension>>(request).await?;

NoCustomData is the other end of the trade: it accepts whatever a peer sends and discards it, costing one byte per node instead of the field's full width - worth naming on an MCU.


๐Ÿ’“ Keepalive & WebSocketPingInterval

By default a client pings the CSMS every 60 seconds and, after two unanswered pings, drops the connection and redials. Without this a half-open link - a dropped NAT entry, a mobile connection that vanished without a FIN - is undetectable: the socket accepts writes and nothing ever comes back, and reconnect can't help because nothing reports the connection as closed.

use ocpp_client::{ConnectOptions, KeepaliveBehavior, KeepalivePolicy, connect_1_6};
use std::time::Duration;

let options = ConnectOptions {
    keepalive: KeepaliveBehavior::Enabled(KeepalivePolicy {
        interval: Duration::from_secs(30),
        timeout: None,          // fall back to the client's request timeout
        max_missed: 2,
    }),
    ..Default::default()
};
let client = connect_1_6("wss://example.com/ocpp", Some(options)).await?;

Set keepalive: KeepaliveBehavior::Disabled if the CSMS pings the charge point instead, or if the deployment forbids unsolicited traffic.

This crate does not implement a device model, but it owns the ping timer, so it exposes the value for the layer that does:

OCPP Variable / key Read Write
2.0.1 / 2.1 OCPPCommCtrlr.WebSocketPingInterval (GetVariables/SetVariables) client.ping_interval() client.set_ping_interval(..)
1.6 (security whitepaper) WebSocketPingInterval (GetConfiguration/ChangeConfiguration) client.ping_interval() client.set_ping_interval(..)

Both are non-async, so a GetVariables handler can call them directly. None maps to the spec's 0 (disabled) in both directions, writes take effect immediately rather than after the current interval finishes, and a write can enable pinging on a client that started with keepalive disabled.


๐Ÿงช Testing

OCPP Client is designed for:

  • Integration testing
  • Charge point development
  • Embedded testing
  • CSMS validation
  • Automated test environments

It can be combined with simulators and real charging hardware to validate complete OCPP workflows.


๐Ÿ›ฃ๏ธ Roadmap

Planned improvements:

  • ๐Ÿ”Œ Additional embedded transports
  • ๐Ÿ“š More examples
  • ๐Ÿงช Expanded integration tests
  • ๐Ÿ”ง Improved developer tooling

๐Ÿค Contributing

Contributions are welcome!

You can help by:

  • ๐Ÿ› Reporting issues
  • ๐Ÿ’ก Suggesting improvements
  • ๐Ÿ“ Improving documentation
  • ๐Ÿ”ง Submitting pull requests

๐Ÿ“„ License

OCPP Client is dual licensed:

  • MIT License
  • Apache License 2.0

You may choose either license.


๐Ÿข About Flowion

OCPP Client is developed by Flowion AB as part of our effort to make EV charging development more accessible through modern, open-source tooling.

Flowion builds software solutions for electric vehicle charging using open standards such as OCPP, helping developers and businesses build reliable and scalable charging infrastructure.


โญ Support the Project

If you find this library useful:

  • โญ Star the repository
  • ๐Ÿ› Report issues
  • ๐Ÿ’ก Suggest improvements
  • ๐Ÿค Contribute

Together we can make EV charging development easier and more accessible.