One control plane for the whole grid.
GridCtl gives operators and agents a single console and a single CLI over OpenADR and OCPP, backed by one normalized event fabric — deployed the same way to a laptop, EC2, ECS, EKS, or an AWS-plus-OCI hybrid target.
- OpenADR dispatch
- OCPP charging sessions
- OpenADR → OCPP bridge
- gridctl CLI
- EC2 / ECS / EKS / OCI hybrid
- One Compose-derived model
Dispatch to recovery.
A load-shed or setpoint event targets a site, group, or VEN.
The event maps to an OCPP charging cap where one applies, with a receipt.
Shed, setpoint, and metered load track against the requested target.
Caps clear; lifecycle and compliance history stay intact for review.
Four planes, one product.
The protocol edge changes; the operator surface, event fabric, and deployment model do not.
One human UI, one agent CLI — gridctl.
Protocol-specific edges; everything past them shared.
Events, sessions, and telemetry as durable time-series history.
One Compose-derived source of truth, five targets.
Deployment targets.
| Target | Compute | Ingress | Notes |
|---|---|---|---|
| Local | Docker Compose | localhost | Full stack, one command, for development and demos. |
| EC2 | Single instance | CloudFront | Cheapest cloud rung; the default for a throwaway demo account. |
| ECS Fargate | Fargate tasks + EBS | ALB → CloudFront | Task defs generated from the same Compose model. |
| EKS | EC2 node groups + EBS CSI | NLB → CloudFront | Kubernetes-native mapping of the same model. |
| AWS + OCI hybrid | OCI compute instance | CloudFront (AWS) | Persistent AWS account for DNS/CDN; compute lives off-account. |
gridctl.
A kubectl-inspired CLI over the same capabilities as the console — JSON by default for scripts and agents, a --table flag for humans, one config for switching targets.
- JSON-first output, structured errors, stable exit codes
- Dispatch, cancel, list, and inspect — the same actions the console takes
gridctl config set-target <url>switches targets in one line
$ gridctl events dispatch --target site-west --setpoint-kw 50 --duration 30
{"event_id":"evt_8f2c1a","status":"DISPATCHED","target":"site-west"}
$ gridctl fleet list --table
NAME PROTOCOL STATE LOAD_KW
site-west openadr RESPONDING 41.2
cs-retail-1 ocpp CHARGING 18.4
$ gridctl events cancel evt_8f2c1a
{"event_id":"evt_8f2c1a","status":"CANCELLED"}
Built to be checked, not taken on faith.
Shared interfaces between services are written down and checked, not implied by shared understanding.
Core dispatch, bridge, and fleet flows run through repeatable smoke checks before anything ships.
Cloud deployment manifests are generated from one Compose model, not hand-maintained in parallel.
OpenADR and OCPP facts land in the same time-series store, so history reads the same regardless of edge.