Integration guides

OCPP onboarding cookbook

A 10-step hand-rail for charger vendors and OEM integrators connecting to the PixellEnergy CSMS over OCPP 1.6J · 2.0.1 · 2.1. Covers the WSS endpoint, subprotocol negotiation, TLS Security Profile 2/3, the BootNotification handshake, the vendor-quirk profile registry, and the JT-1..JT-4 joint-test cadence with a PixellEnergy bridge engineer.

1.Audience and prerequisites

This cookbook is for charger vendors, OEM integrators, and CPO firmware engineers wiring an OCPP-capable charging station to the PixellEnergy CSMS. We assume working knowledge of OCPP 1.6J or OCPP 2.0.1 — the cookbook is a hand-rail through the PixellEnergy-specific decisions, not a tutorial on the protocol itself.

You will need, before you start:

  • A tenant slug provisioned by PixellEnergy (your CSMS-as-a-Service contact will issue this — e.g. acme).
  • One or more station IDs registered in the tenant portal at /admin/stations. Each station ID is the stationId in the WSS URL.
  • Security Profile 2 credentials (TLS + Basic Auth) issued by the tenant-admin. Profile 3 (TLS + client certificate) is mandatory for production tenants.
  • Outbound TLS 443 reachability to gw.pixellenergy.com. Cloudflare is the mandatory reverse-proxy hop (R8 in the risk register).

The staging endpoint is wss://gw.staging.pixellenergy.com/ocpp/<tenant>/<station>. Test against staging until the JT-1 dry-run is green.

2.WSS endpoint format

Stations MUST connect over TLS WebSocket to the PixellEnergy gateway. The URL is deterministic per station:

wss://gw.pixellenergy.com/ocpp/<tenantSlug>/<stationId>

Production hostname is gw.pixellenergy.com; staging is gw.staging.pixellenergy.com. Both terminate TLS at Cloudflare and forward to the uWebSockets.js gateway in Mumbai (ap-south-1) — see the SLO dashboard for current regional latency.

3.Subprotocol negotiation

Subprotocol negotiation lives in the gateway. The station SHOULD advertise every protocol version it supports as a comma-separated list in the Sec-WebSocket-Protocol header; the gateway picks the highest mutually-supported version and echoes it back.

HTTP
# Client opens TLS WSS connection. Sec-WebSocket-Protocol is
# negotiated against the CSMS dispatch table.
#
# Single offer (1.6J):
Sec-WebSocket-Protocol: ocpp1.6

# Single offer (2.0.1):
Sec-WebSocket-Protocol: ocpp2.0.1

# Multi-offer (dispatch picks highest mutually-supported):
Sec-WebSocket-Protocol: ocpp2.1, ocpp2.0.1, ocpp1.6
Accepted subprotocol tokens
FieldTypeRequiredNotes
ocpp1.6literaloptionalOCPP 1.6J — JSON over WebSocket. Production-supported.
ocpp2.0.1literaloptionalOCPP 2.0.1 — recommended for new deployments. Required to access the SignedMeterValue tax-grade path.
ocpp2.1literaloptionalOCPP 2.1 — early-access. Falls back to 2.0.1 dispatch if a 2.1-only feature is exercised.

The gateway responds with exactly one negotiated value. If none of the offered protocols are supported, the WSS handshake fails with HTTP 400 + the response body SUBPROTOCOL_MISMATCH.

4.TLS Security Profile 2 / 3

Per the OCPP Security Whitepaper Ed. 3, the PixellEnergy CSMS requires Security Profile 2 minimum (TLS + Basic Auth) for all environments. Profile 3 (TLS + client certificate) is mandatory for production tenants. Profile 1 (TLS-only, no auth) is rejected at the WSS upgrade.

Security Profile 2 (TLS + Basic Auth) — example
HTTP
wss://gw.pixellenergy.com/ocpp/<your-tenant-slug>/<your-station-id>

Authorization: Basic <base64(stationId:password)>

# Sec-WebSocket-Protocol negotiation (see §3) MUST also be sent.
# The Basic Auth credential is issued one-time-only via the tenant-admin
# portal at /admin/stations/<id>/credentials; rotate via the same
# surface. Never embed plaintext credentials in firmware images.

For Profile 3, the station presents an X.509 client certificate issued by the PixellEnergy Sub-CA. Request a CSR signing flow via the same tenant-admin surface; the API uses OCPP 2.0.1 SignCertificate + CertificateSigned to deliver the signed cert in-band on the first successful connection.

5.BootNotification handshake

The first OCPP frame on every fresh WSS connection MUST be BootNotification. The CSMS replies with one of Accepted / Pending / Rejectedplus an interval (seconds) that the station MUST honour as the minimum delay before re-sending a Boot.

OCPP 2.0.1 BootNotification request
JSON
[2,
  "boot-msg-01",
  "BootNotification",
  {
    "reason": "PowerUp",
    "chargingStation": {
      "model": "ZenergizeDC60-V2",
      "vendorName": "Zenergize",
      "firmwareVersion": "2.1.4",
      "serialNumber": "ZN-DC60-V2-001"
    }
  }
]
OCPP 2.0.1 BootNotificationResponse (Accepted)
JSON
[3,
  "boot-msg-01",
  {
    "status": "Accepted",
    "currentTime": "2026-05-18T08:00:00Z",
    "interval": 300
  }
]
OCPP 1.6J BootNotification (same connection — different shape)
JSON
[2,
  "boot-msg-01",
  "BootNotification",
  {
    "chargePointVendor": "Zenergize",
    "chargePointModel": "ZenergizeDC60-V2",
    "firmwareVersion": "1.6.12",
    "chargePointSerialNumber": "ZN-DC60-V1-001"
  }
]
BootNotification fields the PixellEnergy CSMS validates
FieldTypeRequiredNotes
reasonenumrequiredPowerUp · FirmwareUpdate · LocalReset · RemoteReset · ScheduledReset · Triggered · ApplicationReset · Unknown.
chargingStation.modelstringrequiredUsed by the vendor-quirk registry to match a profile. Keep stable across firmware revs.
chargingStation.vendorNamestringrequiredPixellEnergy OEM Compatibility Program badge is keyed off this exact value.
chargingStation.firmwareVersionstringoptionalLogged to OTel attributes for fleet-wide firmware-drift dashboards.
chargingStation.serialNumberstringoptionalWhen present, MUST match the station record provisioned in the operator portal — mismatch = `RegistrationStatus: Rejected`.

6.Vendor-quirk profile registration

The vendor-quirk profile registry is hot-loadable: a new profile is live within 2 hours of registration with no gateway redeploy. If your firmware has a non-standard behaviour (e.g. emits MeterValues outside an active session, sends a custom Reset.reqreason, or returns non-spec status text), register a profile so the dispatcher applies the appropriate adapter:

POST /v1/admin/vendor-quirks/{vendor_id}/profile (super_admin only)
Shell
curl -X POST 'https://api.pixellenergy.com/v1/admin/vendor-quirks/zenergize-dc60/profile' \
  -H 'Authorization: Bearer <your-super-admin-jwt>' \
  -H 'Idempotency-Key: vendor-quirk-register-<your-ulid>' \
  -H 'Content-Type: application/json' \
  -d '{
    "vendor_id": "zenergize-dc60",
    "vendor_name": "Zenergize",
    "boot_notification_model_match": "ZenergizeDC60-.*",
    "quirks": [
      {
        "id": "JT-1-METERVALUES-OUTSIDE-TX",
        "behaviour": "drop",
        "rationale": "Firmware <2.1.0 emits MeterValues with no transactionId outside an active session; per OCPP 1.6J §5.7 this is allowed but our billing path expects transactionId present."
      }
    ]
  }'

The boot_notification_model_match field is a regex tested against chargingStation.model on every fresh BootNotification. The first matching profile wins. Supported quirk behaviour values today: drop, rewrite, warn.

7.Joint-test (JT-N) pattern

PixellEnergy uses a four-step joint-test cadence with a real charger and a PixellEnergy bridge engineer on the call. Each JT is gated by exit criteria; you do NOT progress until the prior JT is green.

FieldTypeRequiredNotes
JT-1staging dry-runrequiredWSS handshake · subprotocol negotiation · BootNotification · 10-min Heartbeat soak.
JT-2session lifecyclerequiredRemoteStart → Authorize → TransactionEvent(Started/Updated/Ended) → MeterValues. Billing parity validated.
JT-3resiliencerequiredLoss-of-network mid-session · firmware-update reboot · CSMS restart while session active.
JT-4production cutoverrequiredProduction tenant slug · Profile 3 client cert · 24h soak · sign-off by tenant CTO + PixellEnergy DPO.

8.Signed firmware (OCPP 2.0.1)

On OCPP 2.0.1, firmware updates pushed by the CSMS are Ed25519-signed. The station MUST verify the signature against the PixellEnergy public key embedded in the boot ROM (delivered via the CSR flow at JT-4) and reject unsigned firmware with FirmwareStatusNotification.status = SignatureVerificationFailed.

OCPP 1.6J does not include a signed-firmware contract. PixellEnergy publishes 1.6J firmware artefacts via Cloudflare R2 with an out-of-band SHA-256 manifest signed via a PixellEnergy GPG key; your firmware bootloader MUST validate the manifest before flashing. Contact the OEM Compatibility team for the public key.

9.Production cutover checklist

  • Profile 3 (TLS + client cert) presented on every connection.
  • JT-1..JT-4 sign-off documented in the tenant portal.
  • Vendor-quirk profile registered + verified hot-reloaded within 2h SLA.
  • BootNotification emits vendorName matching the OEM Compatibility Program registration (badge eligibility).
  • OTel firmwareVersion attribute populated — appears in fleet-drift dashboards.
  • Heartbeat interval honoured (300s default; do not aggressively beat — it does not buy you better SLO and burns the gateway-online-time SLI).
  • For OCPP 2.0.1: SignedMeterValue emitted on every TransactionEvent (else IRN cannot be issued).
  • Out-of-hours pager rotation for your firmware on-call — escalate via the JT-4 sign-off contact within 1 hour of any CSMS-side P1 incident.

10.Support and JT booking

Book a JT-N session by emailing oem-compatibility@pixellenergy.com with the vendor-quirk profile draft + a target tenant slug. The OEM Compatibility team responds within one business day (Mumbai, Mon–Fri, 09:00–18:00 IST).

For RemoteStart / RemoteStop wiring against your own tenant-portal automations, the NATS subject pattern is:

// NATS subject the CSMS publishes to when a tenant
// triggers a remote start via the operator-portal.
//
// Subject pattern:
//   csms.ocpp.<protocol>.<tenantSlug>.<stationId>.RequestStartTransaction
//
// Example (2.0.1):
csms.ocpp.v201.acme.ZN-DC60-V2-001.RequestStartTransaction

See the API reference for the full REST surface, and the OCPI handshake cookbook for peer-roaming integration.