from optimizer.ev.scheduler import EVChargingScheduler, ChargingSession
from optimizer.base import OptimizationConfig
from coordinator import (
DispatchEngine, EventBus, EventType,
OCPPAdapter, AdapterRegistry,
create_ev_charger_state_machine
)
from datetime import datetime, timezone
# --- Layer 3: Optimize ---
config = OptimizationConfig(horizon="24h", resolution="1h")
scheduler = EVChargingScheduler(config=config, site_capacity_kw=200.0, charger_capacity_kw=22.0)
sessions = [
ChargingSession(
vehicle_id="ev_001",
arrival_time=datetime(2025, 1, 15, 8, 0, tzinfo=timezone.utc),
departure_time=datetime(2025, 1, 15, 17, 0, tzinfo=timezone.utc),
energy_needed_kwh=30.0,
max_charge_rate_kw=22.0,
),
]
tariff = {
"energy_rates": [
{"name": "off_peak", "rate": 0.08, "schedule": {"start_time": "00:00", "end_time": "06:59"}},
{"name": "peak", "rate": 0.25, "schedule": {"start_time": "07:00", "end_time": "22:59"}},
{"name": "off_peak_night", "rate": 0.08, "schedule": {"start_time": "23:00", "end_time": "23:59"}}
]
}
result = scheduler.optimize(
sessions=sessions, tariff=tariff,
start_time=datetime(2025, 1, 15, 0, 0, tzinfo=timezone.utc)
)
print(f"Optimization: {result.status}, cost=${result.total_cost:.2f}")
# --- Layer 4: Coordinate ---
bus = EventBus()
registry = AdapterRegistry()
registry.register("ast_ev_001", OCPPAdapter("ocpp_site"))
engine = DispatchEngine(event_bus=bus, adapter_registry=registry)
# Convert schedule to commands
commands = engine.schedule_to_commands(
result.schedule,
asset_map={"ev_001": "ast_ev_001"}
)
print(f"Generated {len(commands)} commands")
# Dispatch pending commands
now = datetime(2025, 1, 15, 9, 0, tzinfo=timezone.utc)
for cmd in engine.get_pending_commands(now):
adapter = registry.get(cmd.asset_id)
engine.dispatch_command(cmd, adapter)
print(f" Dispatched: {cmd.command_type.value} → {cmd.asset_id} "
f"({cmd.parameters['power_kw']:.0f} kW)")