OCPP WS IOocpp-ws-io
Core WebSocket RPC

Quick Start

Get started with simple Client and Server examples.

Client (Charging Station Simulator)

import { OCPPClient, SecurityProfile } from "ocpp-ws-io";

const client = new OCPPClient({
  endpoint: "ws://localhost:3000/api/v1/chargers",
  identity: "CP001",
  protocols: ["ocpp1.6"],
  securityProfile: SecurityProfile.NONE,
  logging: { prettify: true, exchangeLog: true }, // 🌈 Logs formatted IN/OUT traffic directly
});

// Register a handler — params are auto-typed for OCPP 1.6 Reset
client.handle("Reset", ({ params, protocol }) => {
  console.log(`Reset requested (${protocol}):`, params.type);
  return { status: "Accepted" };
});

// Connect and send a BootNotification — version-aware, fully typed
await client.connect();

const response = await client.call("ocpp1.6", "BootNotification", {
  chargePointVendor: "VendorX",
  chargePointModel: "ModelY",
});

console.log("Status:", response.status); // typed: "Accepted" | "Pending" | "Rejected"

// Send a fire-and-forget message safely (won't throw if station disconnects)
const { success } = await client.safeCall("ocpp1.6", "Heartbeat", {});
if (success) client.logger.info("Heartbeat sent successfully!");

Server (Central System)

import { OCPPServer } from "ocpp-ws-io";

const server = new OCPPServer({
  protocols: ["ocpp1.6", "ocpp2.0.1"],
});

// Optional: Add authentication mapped to a specific endpoint path
server.auth((ctx) => {
  // Access connection info
  const { query, headers } = ctx.handshake;
  const token = query.token;

  if (token === "valid-secret") {
    // Determine which OCPP protocol to use
    // and grant the connection
    ctx.accept({ protocol: "ocpp1.6" });
  } else {
    // Reject unauthorized connections
    ctx.reject(401, "Invalid token");
  }
});

// Handle new client connections
server.on("client", async (client) => {
  console.log(`${client.identity} connected (protocol: ${client.protocol})`);

  // Version-aware handlers — params typed per OCPP version
  client.handle("ocpp1.6", "BootNotification", ({ params }) => {
    console.log("OCPP 1.6 Boot:", params.chargePointVendor);
    return {
      status: "Accepted",
      currentTime: new Date().toISOString(),
      interval: 300,
    };
  });

  client.handle("ocpp2.0.1", "BootNotification", ({ params }) => {
    console.log("OCPP 2.0.1 Boot:", params.chargingStation.vendorName);
    return {
      status: "Accepted",
      currentTime: new Date().toISOString(),
      interval: 300,
    };
  });

  // Version-aware call from server to client
  const config = await client.call("ocpp1.6", "GetConfiguration", {
    key: ["HeartbeatInterval"],
  });
  console.log("Config:", config.configurationKey);

  client.on("close", () => {
    console.log(`${client.identity} disconnected`);
  });
});

await server.listen(3000);
console.log("OCPP Server listening on port 3000");

Next Steps

For larger CSMS projects, writing all logic inside a single server.on('client') handler isn't scalable. Check out Connection Routing to learn how to compartmentalize distinct domains using the Express-like OCPPRouter!

On this page