GridMind: Bridging Energy Optimization and Protocol Engineering
Open-source Python library that translates optimised EV charging schedules into OCPP-compliant charger commands.
Problem
Energy optimisation tools (PyPSA, CVXPY) and OCPP protocol libraries exist separately. No tool bridges them:
Optimisation output: Time-series power schedule (W vs time, absolute timestamps, kWh basis, often 100+ intervals)
Charger input requirement: OCPP SetChargingProfile.req JSON (W or A, relative seconds from schedule start, max 1024 periods, specific JSON schema)
Get Prakhar Singh’s stories in your inbox
Join Medium for free to get updates from this writer.
Gap: Translating between these formats and ensuring real-time protocol compliance is non-trivial and currently not standardised.
Solution
GridMind is a full-stack library:
[EV sessions + site constraints + price signal]
↓
[Convex LP solver (CVXPY)]
↓
[Optimised schedule: power vs time]
↓
[OCPP encoder (v1.6 & v2.0.1)]
↓
[Valid SetChargingProfile.req JSON]Inputs
- EV sessions: arrival, departure, initial/target SoC, battery capacity, max charge rate
- Site constraints: feeder power limit, demand response events
- Price signal: time-of-use or real-time (EUR/kWh)
Processing
- Formulates convex LP:
minimize sum(price[t] * power[t] * dt)subject to SoC bounds, power limits, feeder constraint - Solves via CVXPY with CLARABEL solver
- Merges consecutive periods with identical power to reduce OCPP message size
Outputs
- Per-charger optimised schedule (SchedulePeriod objects)
- OCPP 1.6/2.0.1 SetChargingProfile payloads (JSON)
- Metrics: total cost, peak demand, final SoC, feasibility
- Optional: CSV export, matplotlib visualisations
Usage Example
Single EV, price-optimised charging (6pm expensive, 11pm–6am cheap):
from ocpp_optimizer import SingleEVOptimizer, EVSession, PriceSignal, PricePeriod
from datetime import datetime, timezone, timedeltasession = EVSession(
session_id="ev-001",
charger_id="charger-01",
arrival_time=datetime(2026, 6, 1, 18, 0, tzinfo=timezone.utc),
departure_time=datetime(2026, 6, 2, 8, 0, tzinfo=timezone.utc),
initial_soc=30.0,
target_soc=80.0,
battery_capacity_kwh=60.0,
max_charge_rate_w=7360.0
)price_signal = PriceSignal(periods=[
PricePeriod(
start=datetime(2026, 6, 1, 18, 0, tzinfo=timezone.utc),
end=datetime(2026, 6, 1, 23, 0, tzinfo=timezone.utc),
price=0.35
),
PricePeriod(
start=datetime(2026, 6, 1, 23, 0, tzinfo=timezone.utc),
end=datetime(2026, 6, 2, 8, 0, tzinfo=timezone.utc),
price=0.10
),
])optimizer = SingleEVOptimizer(interval_minutes=15)
schedule = optimizer.optimize(session, price_signal=price_signal)# Output: schedule.total_cost = €1.24 (vs €2.10 uncontrolled)
# 0W from 18:00–23:00, 7360W from 23:00–05:30, 3680W from 05:30–08:00from ocpp_optimizer.ocpp.v16 import build_set_charging_profile_request, to_json
ocpp_request = build_set_charging_profile_request(schedule)
ocpp_json = to_json(ocpp_request)
# → Valid OCPP 1.6 SetChargingProfile.req ready to send
Fleet optimisation (10 EVs, shared 50kW feeder):
from ocpp_optimizer import FleetOptimizer, SiteConfigoptimizer = FleetOptimizer(interval_minutes=15)
fleet_schedule = optimizer.optimize(sessions, site_config)# Outputs: per-EV schedules respecting total feeder limit
# Metrics: peak demand 48.2kW, total cost €15.30, all sessions feasible
Key Features
Single EV optimisation, utilizing LP-based cost minimisation algorithms. This works hand-in-hand with Fleet optimisation capabilities, which successfully handles shared feeder constraints and active demand response. On the integration front, both OCPP 1.6 output via SetChargingProfile.req payloads and OCPP 2.0.1 output using a separate encoder module would be present. The system natively processes Price signals via TOU or real-time feeds, alongside Demand response windows for targeted power reduction.
Variables: p[i,t] = charging power for EV i at interval t (W)Objective: minimize Σ_i Σ_t price[t] * p[i,t] * dt / 1000Subject to:
Energy balance: Σ_t p[i,t] * efficiency * dt / 1000 ≥ energy_needed[i]
Power bounds: 0 ≤ p[i,t] ≤ p_max[i]
SoC bounds: soc_min[i] ≤ soc[i,t] ≤ 100%
Feeder limit: Σ_i p[i,t] ≤ P_site_max for all t
Departure: soc[i,T_depart[i]] ≥ target_soc[i]
Convex LP → CVXPY (CLARABEL or ECOS solver) → optimal in <1s for 100 EVs.
OCPP Encoding
Schedule periods are merged (consecutive identical power → single OCPP period) to reduce message size. startPeriod is seconds from schedule start (not absolute timestamp). Validated against OCPP 1.6 JSON schema.
Solver Tolerances
- SoC tolerance: ±0.5% (acceptable undershot vs target)
- Power threshold: 1W (below = zero, eliminates numerical noise)
- Optimality gap: 1e-4 (CVXPY default)
Use Cases
- Protocol Testing for CMS & Charger Developers: Teams use the platform to generate precise, testable
SetChargingProfilepayloads. This allows developers to run comprehensive conformance testing against real-world charging management systems before deployment. - Grid Simulation for Researchers: Academic and corporate researchers utilize the system to model highly responsive, grid-tied charging scenarios. The platform ensures these simulations respect actual, real-world OCPP constraints rather than just theoretical bounds.
- VPP Platforms for Energy Aggregators: Energy aggregators rely on our engine to compute mathematically optimal charging schedules. Once calculated, these schedules are translated and dispatched directly to active charger fleets to maximize efficiency and flexibility.
- Academic Research for Universities & Labs: Higher education and dedicated labs deploy the software to study complex EV-grid interactions. By maintaining protocol-level fidelity, their research translates seamlessly into real-world applications.
- Grid Planning for DSOs & TSOs: Distribution and Transmission System Operators leverage the platform to model true, realistic EV flexibility capacity. This moves operators away from abstract assumptions, grounding network planning in actual equipment and protocol capabilities.
Limitations
- Single-site only (no multi-location coordination)
- Batch mode (not rolling-horizon)
- AC Level 2 only (no DC fast charging)
- No vehicle-to-grid (v1.0)
- No stochastic optimisation (deterministic prices/departures)
- Max 1024 periods per charger (OCPP 1.6 spec limit)
GridMind currently in progress







