Skip to navigation

Plug, charge and unplug

Drive a deployed virtual charger through a full charging session.

You need a running virtual charger (see the Quickstart) and an id tag your CSMS accepts.

export OCPPLAB_TOKEN="<token>"
export CHARGER_IDENTITY="DEMO-CP-001" # the identity you deployed it with
export ID_TAG="<accepted-id-tag>"

The sequence

StepSDK callWhat the charger does
1commands.plugConnectorReports an EV cable plugged into the connector
2commands.startSessionAuthorizes the id tag and starts a transaction
3commands.stopSessionStops the transaction and sends the final meter values
4commands.unplugConnectorReports the cable unplugged

Each call targets chargers with target: one charger by its OCPP identity (the one you chose when you deployed it) or its deployment_id, or every charger of a location_id, optionally narrowed to charger_ids. payload picks the connector; without it, EVSE 1 connector 1 is used.

Full example

Every command returns 202 with one results[].command.id per targeted charger. The example polls each id until the charger reports a final status: applied, rejected, expired or failed. Until the charger has received the command, polling returns 404.

// Plug a deployed virtual charger in, charge, stop and unplug it.
//
// export OCPPLAB_TOKEN="<api-key>"
// export CHARGER_IDENTITY="DEMO-CP-001" # the identity you deployed it with
// export ID_TAG="<accepted-id-tag>"
// npx tsx examples/plug_charge_unplug.ts
//
// Every command returns 202 once it is queued. Each results[].command.id is
// polled with commands.getStatus until the charger reports a final status.
import { OcpplabSDK, OcpplabSDKTypes } from "ocpplab";
const FINAL = new Set(["applied", "rejected", "expired", "failed"]);
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
async function wait(
client: OcpplabSDK,
queued: Promise<OcpplabSDKTypes.OcppLocationCommandResponse>,
): Promise<void> {
for (const result of (await queued).results) {
while (true) {
try {
const status = await client.evcharger.commands.getStatus({ command_id: result.command.id });
if (FINAL.has(status.status)) {
console.log(result.identity, status.event_type, status.status);
break;
}
} catch (error) {
// 404 until the charger has received the command.
if (!(error instanceof OcpplabSDKTypes.NotFoundError)) throw error;
}
await sleep(2_000);
}
}
}
async function main(): Promise<void> {
const client = new OcpplabSDK({ token: process.env.OCPPLAB_TOKEN! });
const target = { identity: process.env.CHARGER_IDENTITY! };
const connector = { evse_id: 1, connector_id: 1 };
await wait(client, client.evcharger.commands.plugConnector({ target, payload: connector }));
await wait(
client,
client.evcharger.commands.startSession({
target,
payload: { id_tag: process.env.ID_TAG!, connector_id: 1 },
}),
);
await sleep(30_000); // let it charge for a while
await wait(client, client.evcharger.commands.stopSession({ target }));
await wait(client, client.evcharger.commands.unplugConnector({ target, payload: connector }));
}
void main();

startSession already plugs the cable in before it authorizes. Call plugConnector first only when you want to test how your CSMS handles a plugged-in, idle charger.

Other commands

The same pattern works for every evcharger.commands.* call, including authorizeIdTag, changeConfiguration, injectFault, clearFault, sendLocalList and powerUpdate. See the API Reference.