Start in three steps
Connect a virtual OCPP 1.6J charge point to your charging station management system (CSMS), then verify registration and charging telemetry.
Before you start: Install SPX with the OCPP package and SPX UI. Start a CSMS that accepts OCPP 1.6J connections. Download the EVSE charge-point model. In this example, SPX initiates the WebSocket connection to your CSMS.
1. Create the virtual charge point
Import the YAML in Models → Load model from file. Create an instance with ocpp_endpoint set to your exact CSMS WebSocket URL, ocpp_subprotocol=ocpp1.6 and a test ocpp_charge_point_id. Start it. Use a CSMS address reachable from SPX; localhost inside Docker refers to the SPX container.
2. Accept the boot request
Check Communication → ocpp and your CSMS logs. Reply to BootNotification with status="Accepted", the current UTC currentTime and interval=30 for this exercise. Reply with the same message ID. Check boot_status in SPX and reply to subsequent Heartbeat requests.
3. Verify charging telemetry
In SPX Scenarios, start session_charging. Success: your CSMS receives Charging status and MeterValues containing energy in Wh, power in W, current in A and voltage in V. Acknowledge these calls with an empty JSON object {}. Status and meter messages repeat every 6 and 5 seconds. After the 25-second scenario finishes, confirm Available on the next status update, then stop the instance.
Protocol communication
Use these settings and messages with the library’s OCPP EVSE charge point model.
- SPX role
- Charge Point / WebSocket client; your CSMS accepts the connection
- CSMS endpoint
- ws://CSMS_HOST:9000/ocpp in this exercise; use the exact path required by your CSMS
- Handshake
- WebSocket subprotocol ocpp1.6; default charge-point identity spx-evse-01
Replace host placeholders with reachable addresses and use your published ports.
Swipe the table to see requests and replies.
| Address / message | Operation / payload | Expected reply |
|---|---|---|
BootNotification | SPX → CSMS: chargePointVendor="Hammerheads EV", chargePointModel="SPX-EVSE" | CSMS → SPX: status="Accepted", currentTime=UTC timestamp, interval=30 in this test |
Heartbeat | SPX → CSMS: {}; model interval 30 seconds | CSMS → SPX: {"currentTime":"<UTC timestamp>"} |
StatusNotification | SPX → CSMS: connectorId=1, status="Available", errorCode="NoError" at idle | CSMS → SPX: {} acknowledgement |
MeterValues | SPX → CSMS: connectorId=1; meterValue array with Wh, W, A and V samples | CSMS → SPX: {} acknowledgement; inspect telemetry at your CSMS |
Values describe this model’s nominal setup unless noted. Live measurements change as the simulation runs.
Example request and reply
Verify boot_status=Accepted and heartbeat updates in SPX. Run session_charging in SPX, then confirm Charging status and changing MeterValues at the CSMS. Status/meter bindings repeat every 6/5 seconds.
SPX → CSMS (example message ID boot-1):
[2,"boot-1","BootNotification",{"chargePointVendor":"Hammerheads EV","chargePointModel":"SPX-EVSE"}]
CSMS → SPX (same ID; example UTC time):
[3,"boot-1",{"status":"Accepted","currentTime":"2026-11-08T12:00:00Z","interval":30}]
SPX → CSMS: [2,"hb-1","Heartbeat",{}]
CSMS → SPX: [3,"hb-1",{"currentTime":"2026-11-08T12:00:30Z"}]No reply or an unexpected value?
- Use your CSMS’s exact URL. The bundled SPX CSMS listens at /ocpp exactly; do not append /spx-evse-01 to that URL. Other CSMS products may require an identity in the path.
- CSMS_HOST must be reachable from SPX. localhost in Docker refers to the SPX container, not your desktop. Include ocpp1.6 in the handshake.
- The example reply is a CSMS response you must provide. This EVSE model has no RemoteStartTransaction/RemoteStopTransaction bindings; session_charging drives the demo locally. Example message IDs/timestamps below are illustrative; replies use the actual request ID and current UTC time.
What you can test next
- Run
fault_groundand inspect the reported fault state. - Compare idle and charging meter samples.
- Review the model’s bindings before adding remote commands. This EVSE example does not bind RemoteStartTransaction or RemoteStopTransaction.
See the OCPP adapter guide for configuration details.
