Skip to content

Latest commit

Β 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Savekar Logo

OCPI 2.2.1 EMSP Simulator

A production-quality, full-featured EMSP simulator for validating OCPI 2.2.1 CPO implementations

License Python OCPI FastAPI PRs Welcome GitHub Issues

Overview Β· Features Β· Quick Start Β· Usage Β· Contributing Β· Contact


🏒 About Savekar

Savekar is an Indian EV technology company building the infrastructure for the electric vehicle revolution. We develop open, standards-based software for EV charging networks β€” including Charge Point Management Systems (CPMS), OCPP & OCPI protocol stacks, and fleet management tooling.

We believe open-source collaboration is key to accelerating EV adoption. This simulator is one of our open-source contributions to the global EV developer community.

🌐 Website: savekar.com πŸ“§ Contact: savekarev@gmail.com πŸ’¬ Discord: Join our community πŸ’Ό GitHub Org: github.com/savekar


🀝 Test Your OCPI Integration With Us

Are you building a production-grade CPO and want to validate your OCPI implementation against a real EMSP before going live with a roaming partner?

We offer connectivity testing against our hosted EMSP simulator. Reach out to us and we'll help you verify your OCPI handshake, Location pushes, Session updates, CDR submissions, Commands, and Tokens are spec-compliant.


πŸ“– Overview

The OCPI 2.2.1 EMSP Simulator is a comprehensive, developer-focused tool designed to simulate an e-Mobility Service Provider (EMSP) that communicates strictly via the Open Charge Point Interface (OCPI) 2.2.1 protocol.

It is used to validate that a Charge Point Operator (CPO) backend correctly implements the OCPI 2.2.1 specification β€” covering credentials exchange, location synchronization, token management, session lifecycle, commands, and CDR submission β€” before integrating with real roaming partners.

⚠️ Scope & Limitations

Limitation Details
Not a Production EMSP Testing-only tool. Does not handle real payments, user management, or business logic.
OCPI 2.2.1 Only Strictly adheres to OCPI version 2.2.1.
Partial Commands Support START_SESSION and STOP_SESSION are supported. UNLOCK_CONNECTOR and RESERVE_NOW return NOT_SUPPORTED.
Schema Validation Uses official OCPI 2.2.1 JSON schemas. May not cover every edge case of the full specification.

πŸ‘₯ Intended Audience

This simulator is built for:

  • Backend Engineers building CPO platforms who need EMSP validation.
  • EV Platform Developers testing OCPI compliance before going live with roaming partners.
  • QA & Integration Teams running automated protocol validation pipelines.

βœ… What This Simulator Validates

  • βœ… OCPI endpoint direction and correct usage
  • βœ… Credentials handshake (Token A β†’ B β†’ C exchange)
  • βœ… Token rotation (PUT /credentials)
  • βœ… Schema correctness for Locations, Sessions, CDRs, Tokens, and Commands
  • βœ… OCPI response envelope and status code semantics
  • βœ… EVSE status PATCH updates
  • βœ… Token registration and management (RFID, APP_USER, OTHER)
  • βœ… Command handling (START_SESSION, STOP_SESSION) with async callbacks
  • βœ… Session lifecycle (PUT full session, PATCH updates, GET queries)
  • βœ… CDR ingestion and validation with pagination
  • βœ… Date filtering and pagination on Sessions and CDRs

❌ What It Does NOT Validate

  • ❌ Commercial settlement or billing rules
  • ❌ Partner-specific extensions or quirks
  • ❌ Certification-level compliance
  • ❌ Real-world EMSP operational behavior
  • ❌ UNLOCK_CONNECTOR and RESERVE_NOW commands (returns NOT_SUPPORTED)

πŸ—οΈ Architectural Design

The EMSP Simulator is designed with a clear separation between passive endpoints (for CPO-initiated pushes) and active test clients (for EMSP-initiated requests).

flowchart TB
    CPO(("πŸ‘€ Target CPO Backend<br/>(Under Test)"))

    subgraph "OCPI 2.2.1 EMSP Simulator"
        direction TB
        UI["πŸ’» Web Dashboard<br/>(ui/)"]
        Tests["πŸ€– Active Test Client<br/>(verify_cpo.py)"]

        subgraph "FastAPI Server"
            direction LR
            Endpoints["πŸ”Œ OCPI Endpoints<br/>(app/routes)"]
            Validators{"βœ… Schema Validation<br/>(app/validators)"}
            State[("🧠 State Manager<br/>(app/state.py)")]

            Endpoints --> Validators
            Validators --> State
        end

        UI -.->|Reads state| State
    end

    CPO == "HTTP POST/PUT/PATCH<br/>(Push Sessions, CDRs)" ==> Endpoints
    CPO == "HTTP GET<br/>(Pull Locations, Tariffs)" ==> Endpoints
    Tests == "HTTP GET/POST<br/>(Test CPO All Endpoints)" ==> CPO
Loading

✨ Features

Feature Description
Full OCPI 2.2.1 Compliance Implements all core modules: Versions, Credentials, Locations, Tokens, Sessions, Commands, CDRs
Strict Schema Validation Validates incoming OCPI data against official 2.2.1 JSON schemas. HTTP status is configurable (200 or 400).
Credentials Handshake Full implementation of the CREDENTIALS module including token rotation (PUT).
Token Management Complete Token module support (PUT, PATCH, GET) for RFID, APP_USER, and OTHER token types.
Command Support START_SESSION and STOP_SESSION commands with async callback handling.
Session Management Full session lifecycle with PUT (creation), PATCH (updates), and GET (queries).
CDR Ingestion Accepts and validates Charge Detail Records with pagination support.
Pagination & Filtering Sessions and CDRs support offset/limit pagination and date range filtering.
Active Test Client Comprehensive CPO client that calls all CPO endpoints for validation.
Structured Logging Context-rich logs with direction, module, and payload details.
Web Dashboard Comprehensive browser-based dashboard with real-time stats, token management, commands, and state inspection.
Verification Script verify_cpo.py β€” one-command PASS/FAIL validation of all 16 endpoint categories.

πŸš€ Quick Start

Prerequisites

  • Python 3.8 or higher
  • pip (Python package installer)
  • A running CPO implementation to test against

1. Clone the Repository

git clone https://github.com/savekar/OCPI-2.2.1-EMSP-Simulator.git
cd OCPI-2.2.1-EMSP-Simulator

2. Install Dependencies

pip install -r requirements.txt

Tip: Use a virtual environment to keep your dependencies isolated:

python -m venv venv
source venv/bin/activate        # Linux/macOS
venv\Scripts\activate.bat       # Windows
pip install -r requirements.txt

3. Configure

Copy the example configuration and edit it for your environment:

cp config.example.yaml config.yaml
# On Windows (if cp is not available):
# copy config.example.yaml config.yaml

Edit config.yaml with your CPO's details:

Setting Description Default
host Interface to bind to 127.0.0.1
port Port to listen on 8000
party_id EMSP party ID (3 letters) ION
country_code EMSP country code (2 letters) IN
bootstrap_token Token expected from CPO for initial handshake (Token A) β€”
emsp_token_to_cpo Token sent by Simulator to CPO in requests (Token C) β€”
cpo_token_to_emsp Token expected from CPO after handshake (Token B) β€”
cpo_url Base URL of your CPO's OCPI API β€”

4. Start the Simulator

python run.py

The simulator will start at http://127.0.0.1:8000 (or your configured host/port).

Open your browser and navigate to http://localhost:8000 to access the Web Dashboard, where you can:

  • Configure connection settings and EMSP identity
  • Perform credentials handshake and token rotation
  • Register and manage tokens
  • Send START_SESSION and STOP_SESSION commands
  • View real-time statistics (tokens, sessions, CDRs, commands)
  • Monitor logs and inspect simulator state

πŸ“š Usage Guide

OCPI Endpoints Exposed

Simulator Endpoints (CPO calls EMSP)

Module Method Endpoint Description
Versions GET /ocpi/versions Return available OCPI versions
Versions GET /ocpi/emsp/2.2.1 Return EMSP endpoint details
Credentials GET, POST, PUT /ocpi/emsp/2.2.1/credentials Credentials exchange and token rotation
Locations PATCH /ocpi/emsp/2.2.1/locations/{id}/{evse_uid} Receive EVSE status updates
Sessions GET, PUT, PATCH /ocpi/emsp/2.2.1/sessions/{...} Session management
CDRs GET, POST /ocpi/emsp/2.2.1/cdrs/{...} CDR ingestion and retrieval
Tokens GET, PUT, PATCH /ocpi/emsp/2.2.1/tokens/{cc}/{party}/{uid} Token registration and management
Commands POST /ocpi/emsp/2.2.1/commands/START_SESSION Start charging session
Commands POST /ocpi/emsp/2.2.1/commands/STOP_SESSION Stop charging session
Commands POST /ocpi/emsp/2.2.1/commands/UNLOCK_CONNECTOR Not supported
Commands POST /ocpi/emsp/2.2.1/commands/RESERVE_NOW Not supported

CPO Endpoints (Simulator calls CPO)

Module Method Endpoint Description
Versions GET /ocpi/versions Get available versions
Versions GET /ocpi/cpo/2.2.1/details Get CPO endpoint details
Credentials GET, POST, PUT /ocpi/cpo/2.2.1/credentials Credentials exchange
Locations GET /ocpi/cpo/2.2.1/locations/{id} Get locations with pagination
Tariffs GET /ocpi/cpo/2.2.1/tariffs/{id} Get tariffs
Sessions GET /ocpi/cpo/2.2.1/sessions/{id} Get sessions with pagination
CDRs GET /ocpi/cpo/2.2.1/cdrs/{id} Get CDRs with pagination
Tokens GET, PUT, PATCH /ocpi/cpo/2.2.1/tokens/{cc}/{party}/{uid} Token operations
Commands POST /ocpi/cpo/2.2.1/commands/START_SESSION Start session command
Commands POST /ocpi/cpo/2.2.1/commands/STOP_SESSION Stop session command
Commands POST /ocpi/cpo/2.2.1/commands/UNLOCK_CONNECTOR Unlock connector (not supported)
Commands POST /ocpi/cpo/2.2.1/commands/RESERVE_NOW Reserve now (not supported)

Step 1: Credentials Handshake

Your CPO must initiate the connection by performing the OCPI credentials exchange:

  1. Ensure bootstrap_token in config.yaml matches what your CPO will send.
  2. From your CPO, send a POST request to:
    POST http://localhost:8000/ocpi/emsp/2.2.1/credentials
    Authorization: Token <bootstrap_token>
    
  3. The simulator validates your request, stores your credentials, and returns its own (including emsp_token_to_cpo).

Step 2: Run the Verification Script

Use the bundled script to actively test your CPO's OCPI endpoints:

python verify_cpo.py

This script will test 16 endpoint categories:

  1. GET /versions
  2. GET /2.2.1/details
  3. POST /2.2.1/credentials (Handshake)
  4. GET /2.2.1/credentials
  5. GET /2.2.1/locations
  6. GET /2.2.1/tariffs
  7. PUT /2.2.1/tokens (Register token)
  8. GET /2.2.1/tokens (Retrieve token)
  9. PATCH /2.2.1/tokens (Update token)
  10. POST /2.2.1/commands/START_SESSION
  11. POST /2.2.1/commands/STOP_SESSION
  12. POST /2.2.1/commands/UNLOCK_CONNECTOR
  13. POST /2.2.1/commands/RESERVE_NOW
  14. GET /2.2.1/sessions
  15. GET /2.2.1/cdrs
  16. PUT /2.2.1/credentials (Token Rotation)

Logs & Debugging

The simulator writes structured logs to stdout and optionally to a file (configured in config.yaml):

[CPO→EMSP][credentials] Invalid Token {Token=abc123...}
[EMSP→CPO][sessions]    Session update accepted {session_id=xyz}

Format: [Direction][Module] Message {Context}


πŸ’» Web Dashboard

The simulator includes a comprehensive web dashboard accessible at http://localhost:8000 (or your configured host/port).

Dashboard Features

Real-Time Statistics

  • Tokens Counter: Shows number of registered tokens
  • Sessions Counter: Shows active and completed sessions
  • CDRs Counter: Shows received Charge Detail Records
  • Commands Counter: Shows executed commands
  • Auto-refreshes every 5 seconds

Configuration Panel

  • Update CPO API URL
  • Configure Bootstrap Token (Token A)
  • Set EMSP Party ID and Country Code

Discovery & Credentials

  • Credentials Exchange (POST)
  • Get Credentials (GET)
  • Token Rotation (PUT)
  • Get Versions and Details
  • Fetch Locations and Tariffs

Token Management

  • Register New Tokens:
    • Support for RFID, APP_USER, and OTHER types
    • Whitelist configuration (ALLOWED, ALWAYS, ALLOWED_OFFLINE, NEVER)
    • Valid/Invalid status
  • Update Tokens: Enable or disable existing tokens
  • Query Tokens: Retrieve token details by UID

Commands

  • START_SESSION: Start charging sessions with full parameters
  • STOP_SESSION: Stop sessions by Session ID
  • Shows unsupported commands (UNLOCK_CONNECTOR, RESERVE_NOW)

Sessions & CDRs

  • Query all sessions with pagination
  • Get session details by ID
  • Query all CDRs with pagination
  • Get CDR details by ID

Logs & State Viewer

  • Tabbed Interface: Switch between Logs and State view
  • Colored Log Entries:
    • 🟒 Success messages (green)
    • πŸ”΅ Info messages (blue)
    • πŸ”΄ Error messages (red)
  • State Inspector: View complete simulator state including all data
  • Auto-scroll to latest log entries
  • Clear logs functionality

Dashboard API Endpoints

The UI exposes 23 API endpoints for dashboard functionality:

Category Endpoints
Configuration GET/POST /ui/config
Credentials POST /ui/actions/credentials/*
Discovery POST /ui/actions/{versions,details,locations,tariffs}
Tokens POST /ui/actions/tokens/{register,update,get}
Commands POST /ui/actions/commands/{start_session,stop_session}
Sessions POST /ui/actions/sessions/*
CDRs POST /ui/actions/cdrs/*
State GET /ui/state*

πŸ“ Project Structure

OCPI-2.2.1-EMSP-Simulator/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ routes/              # Server-side OCPI endpoint handlers
β”‚   β”‚   β”œβ”€β”€ versions.py      # Version discovery endpoints
β”‚   β”‚   β”œβ”€β”€ credentials.py   # Credentials and token management
β”‚   β”‚   β”œβ”€β”€ locations.py     # Location and EVSE updates
β”‚   β”‚   β”œβ”€β”€ sessions.py      # Session lifecycle management
β”‚   β”‚   β”œβ”€β”€ cdrs.py          # CDR ingestion and retrieval
β”‚   β”‚   β”œβ”€β”€ tokens.py        # Token registration and management
β”‚   β”‚   β”œβ”€β”€ commands.py      # Command handling with callbacks
β”‚   β”‚   └── ui.py            # Web dashboard routes
β”‚   β”œβ”€β”€ client/              # Client-side logic to call CPO endpoints
β”‚   β”‚   └── cpo_client.py    # Comprehensive CPO client
β”‚   β”œβ”€β”€ validators/
β”‚   β”‚   └── json_schemas/    # Official OCPI 2.2.1 JSON schemas
β”‚   β”œβ”€β”€ config.py            # Configuration loader
β”‚   β”œβ”€β”€ log_utils.py         # Structured logging utilities
β”‚   β”œβ”€β”€ state.py             # In-memory state management
β”‚   └── main.py              # FastAPI application setup
β”œβ”€β”€ tests/                   # Automated verification scripts
β”œβ”€β”€ ui/                      # Comprehensive HTML/JS web dashboard with token management, commands, and state viewer
β”œβ”€β”€ config.example.yaml      # Example configuration file
β”œβ”€β”€ run.py                   # Application entrypoint
β”œβ”€β”€ verify_cpo.py            # Comprehensive CPO validation script
└── requirements.txt         # Python dependencies

🀝 Contributing

We welcome contributions from the community! Whether it's a bug fix, new feature, or documentation improvement β€” all contributions are appreciated.

Please read our Contributing Guide before submitting a pull request.

Quick steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Make your changes and write tests
  4. Commit: git commit -m "feat: add your feature"
  5. Push: git push origin feature/your-feature-name
  6. Open a Pull Request

πŸ›‘οΈ Security

If you discover a security vulnerability, please do not open a public GitHub issue. Instead, follow our Security Policy and report it privately.


πŸ“„ License

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.


πŸ“¬ Contact & Support

Channel Link
πŸ“§ Email savekarev@gmail.com
πŸ› Bug Reports Open an Issue
πŸ’¬ Discussions GitHub Discussions
πŸ’¬ Discord Join our community
🌐 Website savekar.com
πŸ”Œ OCPI Testing savekar.com/ocpi-simulator

Built with ❀️ by the Savekar team · Powering the EV revolution with open standards

About

A lightweight Python-based OCPI 2.2.1 EMSP Simulator to validate CPO protocol correctness, credentials handshake, and schema compliance

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages