# mharisnaveed/iso15118_evcat architecture

> Architecture diagram of the GitHub repository mharisnaveed/iso15118_evcat, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mharisnaveed/iso15118_evcat
- Repository: https://github.com/mharisnaveed/iso15118_evcat

## Overview

1. **System shape**
   - This repo is a two-node ISO 15118 deployment: an **EVCC** process on one Raspberry Pi and a **SECC** process on another, connected only through a **PLC bridge**.  
   - The physical/data-link side is handled by the PLC network; the application side is the ISO 15118 session implemented in Python under `iso15118_core`.

2. **Top-level deployment boundaries**
   - `EVCC_Client/` contains the vehicle-side runner scripts.
   - `SECC_Master/` contains the charger-side runner scripts.
   - `config/` holds network and host setup for the Raspberry Pi/PLC environment.
   - `logs/` stores captured session logs and historical runs.
   - `iso15118_core/` is the actual protocol stack and custom battery-test extension layer.

3. **Startup and process ownership**
   - Each side is a separate process with its own configuration and controller state; there is no shared memory between EVCC and SECC.
   - The `main.py` modules under `iso15118/evcc/` and `iso15118/secc/` are the primary application entry points into the protocol stack.

4. **Transport path**
   - Discovery starts with **SDP over UDP multicast** on link-local IPv6.
   - After discovery, the nodes establish **TCP**, then upgrade to **TLS 1.3** before exchanging V2G application messages.
   - The transport layer is split cleanly into `udp_client.py` / `udp_server.py` and `tcp_client.py` / `tcp_server.py`.

5. **Protocol engine and message model**
   - The repo follows the ISO 15118 layering: shared message definitions, schema-backed message types, and protocol state machines.
   - `iso15118/shared/messages/` and `iso15118/shared/schemas/` define the protocol payloads for DIN SPEC, ISO 15118-2, and ISO 15118-20.
   - The state-machine implementations live in `evcc/states/` and `secc/states/`, separated by protocol version and energy-service family.

6. **Session orchestration**
   - `comm_session_handler.py` on each side coordinates the session lifecycle: protocol negotiation, authorization, service discovery, service selection, and charge-loop execution.
   - `shared/comm_session.py` holds the common session abstractions used by both roles.
   - This is the main boundary where transport events are converted into protocol-state transitions.

7. **Controller abstraction**
   - Both EVCC and SECC use controller interfaces to isolate protocol logic from the “real world.”
   - `controller/interface.py` defines the expected controller contract, while `controller/simulator.py` provides simulated implementations.
   - On the SECC side, `ev_data.py` and `evse_data.py` package the negotiated limits and runtime state that flow through the session.

8. **Battery diagnostic extension layer**
   - The project’s main custom addition is `shared/battery_diagnostics/`, which implements a **Value-Added Services** framework on top of ISO 15118-20.
   - `registry.py` routes a selected diagnostic service by service ID.
   - `base_service.py` defines the service interface, and `telemetry.py` writes the final report.
   - `services/health_test.py` is the implemented battery discharge-capacity service; EIS and HPPC are planned placeholders in the architecture.

9. **Battery physics model**
   - `battery_simulator.py` is intentionally separated from protocol and service logic.
   - It provides the SOC/voltage/thermal behavior used by the diagnostic service, so the protocol layer only sees charging/discharging commands and measured telemetry.
   - This separation is important for diagramming: protocol state machine, diagnostic service sequencing, and battery model are three distinct layers.

10. **Security and PKI**
   - Security is not optional glue here; it is part of the main architecture.
   - `shared/security.py`, `shared/pki/`, and the cert config files support the TLS/Plug-and-Charge-style certificate chain.
   - The repo includes certificate generation tooling and sample configs, indicating that security setup is an explicit deployment step, not a runtime afterthought.

11. **Standard and version partitioning**
   - The implementation supports multiple standards branches: **DIN SPEC**, **ISO 15118-2**, and **ISO 15118-20**.
   - The current project focus is ISO 15118-20 because it natively supports **BPT** and **VAS**, which are required for the discharge-based battery tests.
   - This means there are parallel protocol trees, but the architecture is centered on ISO 15118-20 for the diagnostic use case.

12. **Infrastructure and operational tooling**
   - `docker-compose*.yml`, `Makefile`, and `.env` files support local and containerized execution of the protocol stack.
   - `config/setup_plc_network.sh` and `config/dhcpcd.conf` reflect the Raspberry Pi + PLC networking setup.
   - `tests/` covers protocol states, message validation, security, and the new diagnostic framework, showing that behavior is validated at both the standards and service layers.

13. **External integration points**
   - The physical PLC hardware is the transport boundary to the real world.
   - The current architecture also leaves room for future hardware/BMS integration, but today the diagnostic layer runs on the simulated battery model.
   - Diagnostic telemetry is emitted as a JSON report at session end, which is the main data product produced outside the live protocol exchange.

14. **How to draw the diagram**
   - Draw two separate runtime nodes: **EVCC client** and **SECC master**.
   - Between them, show **SDP discovery over UDP**, then **TCP/TLS 1.3**, then the **ISO 15118-20 session**.
   - Inside the SECC node, show the flow from session handler to controller to diagnostic service registry to battery simulator/telemetry.
   - Inside the EVCC node, show the mirrored session/state machine path and the client-side controller/transport boundary.

Main entry points: [`iso15118_core/iso15118/secc/comm_session_handler.py`](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/comm_session_handler.py) (SECC session), [`iso15118_core/iso15118/evcc/comm_session_handler.py`](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/comm_session_handler.py) (EVCC session), [`iso15118_core/iso15118/evcc/transport/udp_client.py`](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/transport/udp_client.py) (EVCC transport), [`iso15118_core/iso15118/secc/transport/udp_server.py`](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/transport/udp_server.py) (SECC transport)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_deployment["Deployment"]
  node_evcc_main["EVCC main<br/>entrypoint<br/>[main.py]"]
  node_secc_main["SECC main<br/>entrypoint<br/>[main.py]"]
end

subgraph group_protocol["Protocol Stack"]
  node_evcc_session["EVCC session<br/>orchestrator"]
  node_secc_session["SECC session<br/>orchestrator"]
  node_evcc_states{{"EVCC states<br/>state machine"}}
  node_secc_states{{"SECC states<br/>state machine"}}
  node_evcc_transport["EVCC transport<br/>client transport<br/>[udp_client.py]"]
  node_secc_transport["SECC transport<br/>server transport<br/>[udp_server.py]"]
  node_evcc_controller["EVCC controller<br/>[interface.py]"]
  node_secc_controller["SECC controller<br/>[interface.py]"]
end

subgraph group_shared["Shared Core"]
  node_comm_session["Shared session<br/>session core<br/>[comm_session.py]"]
  node_messages["Messages<br/>payload model<br/>[__init__.py]"]
  node_schemas["Schemas<br/>xsd model<br/>[__init__.py]"]
  node_security["Security<br/>tls/pki<br/>[security.py]"]
  node_pki["PKI<br/>certificate config<br/>[create_certs.sh]"]
end

subgraph group_diagnostics["Battery Diagnostics"]
  node_diag_registry{{"VAS registry<br/>service router<br/>[registry.py]"}}
  node_diag_service["Health test<br/>diagnostic service<br/>[health_test.py]"]
  node_battery_sim[("Battery model<br/>physics model")]
  node_telemetry["Telemetry<br/>reporting<br/>[telemetry.py]"]
end

subgraph group_ops["Operations"]
  node_network_setup["PLC setup<br/>deployment config"]
  node_logs["Logs<br/>runtime output<br/>[EVCC.txt]"]
end

node_evcc_main -->|"starts"| node_evcc_session
node_secc_main -->|"starts"| node_secc_session
node_evcc_session -->|"drives"| node_evcc_states
node_secc_session -->|"drives"| node_secc_states
node_evcc_session -->|"uses"| node_evcc_transport
node_secc_session -->|"uses"| node_secc_transport
node_evcc_session -->|"calls"| node_evcc_controller
node_secc_session -->|"calls"| node_secc_controller
node_evcc_session -->|"builds on"| node_comm_session
node_secc_session -->|"builds on"| node_comm_session
node_evcc_states -->|"encodes"| node_messages
node_secc_states -->|"encodes"| node_messages
node_messages -->|"validated by"| node_schemas
node_evcc_transport -->|"SDP / UDP"| node_secc_transport
node_evcc_transport -->|"TCP / TLS 1.3"| node_secc_transport
node_security -->|"depends on"| node_pki
node_secc_session -->|"selects"| node_diag_registry
node_diag_registry -->|"routes to"| node_diag_service
node_diag_service -->|"simulates"| node_battery_sim
node_diag_service -->|"reports"| node_telemetry
node_network_setup -.->|"enables"| node_secc_transport
node_network_setup -.->|"enables"| node_evcc_transport
node_logs -.->|"captures"| node_evcc_session
node_logs -.->|"captures"| node_secc_session

click node_evcc_main "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/main.py"
click node_secc_main "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/main.py"
click node_evcc_session "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/comm_session_handler.py"
click node_secc_session "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/comm_session_handler.py"
click node_evcc_states "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/states/iso15118_20_states.py"
click node_secc_states "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/states/iso15118_20_states.py"
click node_evcc_transport "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/transport/udp_client.py"
click node_secc_transport "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/transport/udp_server.py"
click node_evcc_controller "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/controller/interface.py"
click node_secc_controller "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/controller/interface.py"
click node_comm_session "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/comm_session.py"
click node_messages "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/messages/__init__.py"
click node_schemas "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/schemas/__init__.py"
click node_security "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/security.py"
click node_pki "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/pki/create_certs.sh"
click node_diag_registry "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/registry.py"
click node_diag_service "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/services/health_test.py"
click node_battery_sim "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/battery_simulator.py"
click node_telemetry "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/telemetry.py"
click node_network_setup "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/config/setup_plc_network.sh"
click node_logs "https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/logs/EVCC.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_evcc_main,node_secc_main toneBlue
class node_evcc_session,node_secc_session,node_evcc_states,node_secc_states,node_evcc_transport,node_secc_transport,node_evcc_controller,node_secc_controller toneAmber
class node_comm_session,node_messages,node_schemas,node_security,node_pki toneMint
class node_diag_registry,node_diag_service,node_battery_sim,node_telemetry toneRose
class node_network_setup,node_logs toneIndigo
```

## Components

### Deployment

Runtime processes and environment boundaries

- [EVCC main](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/main.py): entrypoint · Vehicle-side process entry point · `iso15118_core/iso15118/evcc/main.py`
- [SECC main](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/main.py): entrypoint · Charger-side process entry point · `iso15118_core/iso15118/secc/main.py`

### Protocol Stack

EVCC/SECC session logic and transport

- [EVCC session](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/comm_session_handler.py): orchestrator · EVCC session lifecycle and state dispatch · `iso15118_core/iso15118/evcc/comm_session_handler.py`
- [SECC session](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/comm_session_handler.py): orchestrator · SECC session lifecycle and state dispatch · `iso15118_core/iso15118/secc/comm_session_handler.py`
- [EVCC states](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/states/iso15118_20_states.py): state machine · DIN SPEC, ISO 15118-2, and ISO 15118-20 EVCC states · `iso15118_core/iso15118/evcc/states/iso15118_20_states.py`
- [SECC states](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/states/iso15118_20_states.py): state machine · DIN SPEC, ISO 15118-2, and ISO 15118-20 SECC states · `iso15118_core/iso15118/secc/states/iso15118_20_states.py`
- [EVCC transport](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/transport/udp_client.py): client transport · SDP discovery and TCP client path · `iso15118_core/iso15118/evcc/transport/udp_client.py`
- [SECC transport](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/transport/udp_server.py): server transport · SDP responder and TCP server path · `iso15118_core/iso15118/secc/transport/udp_server.py`
- [EVCC controller](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/evcc/controller/interface.py): controller · EVCC world-interface abstraction · `iso15118_core/iso15118/evcc/controller/interface.py`
- [SECC controller](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/secc/controller/interface.py): controller · SECC world-interface abstraction · `iso15118_core/iso15118/secc/controller/interface.py`

### Shared Core

Common message, security, and session primitives

- [Shared session](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/comm_session.py): session core · Common comm-session abstractions · `iso15118_core/iso15118/shared/comm_session.py`
- [Messages](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/messages/__init__.py): payload model · Shared protocol message definitions · `iso15118_core/iso15118/shared/messages/__init__.py`
- [Schemas](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/schemas/__init__.py): xsd model · DIN SPEC, ISO 15118-2, and ISO 15118-20 schemas · `iso15118_core/iso15118/shared/schemas/__init__.py`
- [Security](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/security.py): tls/pki · TLS and Plug-and-Charge security helpers · `iso15118_core/iso15118/shared/security.py`
- [PKI](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/pki/create_certs.sh): certificate config · Certificate configs and generation tooling · `iso15118_core/iso15118/shared/pki/create_certs.sh`

### Battery Diagnostics

Custom service layer and battery model

- [VAS registry](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/registry.py): service router · Routes battery diagnostic services by ID · `iso15118_core/iso15118/shared/battery_diagnostics/registry.py`
- [Health test](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/services/health_test.py): diagnostic service · Battery discharge-capacity service · `iso15118_core/iso15118/shared/battery_diagnostics/services/health_test.py`
- [Battery model](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/battery_simulator.py): physics model · SOC, voltage, and thermal behavior · `iso15118_core/iso15118/shared/battery_diagnostics/battery_simulator.py`
- [Telemetry](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/iso15118_core/iso15118/shared/battery_diagnostics/telemetry.py): reporting · Final session report writer · `iso15118_core/iso15118/shared/battery_diagnostics/telemetry.py`

### Operations

Network setup, configs, and logs

- [PLC setup](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/config/setup_plc_network.sh): deployment config · Raspberry Pi and PLC network setup · `config/setup_plc_network.sh`
- [Logs](https://github.com/mharisnaveed/iso15118_evcat/blob/Dedicated_Added_Services_Structured/logs/EVCC.txt): runtime output · Captured session logs and historical runs · `logs/EVCC.txt`

## Connections

- EVCC main → EVCC session: starts · EVCC entry point creates the session handler
- SECC main → SECC session: starts · SECC entry point creates the session handler
- EVCC session → EVCC states: drives · Session events advance EVCC protocol states
- SECC session → SECC states: drives · Session events advance SECC protocol states
- EVCC session → EVCC transport: uses · Session handler receives discovery and TCP/TLS events
- SECC session → SECC transport: uses · Session handler accepts discovery and TCP/TLS events
- EVCC session → EVCC controller: calls · Protocol state machine consults EV controller abstraction
- SECC session → SECC controller: calls · Protocol state machine consults SE controller abstraction
- EVCC session → Shared session: builds on · EVCC session uses shared comm-session primitives
- SECC session → Shared session: builds on · SECC session uses shared comm-session primitives
- EVCC states → Messages: encodes · EVCC states exchange shared protocol messages
- SECC states → Messages: encodes · SECC states exchange shared protocol messages
- Messages → Schemas: validated by · Shared payloads are backed by standards schemas
- EVCC transport → SECC transport: SDP / UDP · Link-local multicast discovery over UDP
- EVCC transport → SECC transport: TCP / TLS 1.3 · Post-discovery V2G session transport
- Security → PKI: depends on · TLS and Plug-and-Charge trust material come from PKI config
- SECC session → VAS registry: selects · ISO 15118-20 service selection routes to a diagnostic service
- VAS registry → Health test: routes to · Selected service is instantiated by service ID
- Health test → Battery model: simulates · Diagnostic service reads battery behavior from the model
- Health test → Telemetry: reports · Service writes final telemetry report
- PLC setup → SECC transport: enables · PLC network setup supports charger-side transport
- PLC setup → EVCC transport: enables · PLC network setup supports vehicle-side transport
- Logs → EVCC session: captures · Runtime logs reflect EVCC session execution
- Logs → SECC session: captures · Runtime logs reflect SECC session execution
