OCPP WS IO

Integration

Integrate ocpp-ws-io Server and Client with Node.js frameworks.

ocpp-ws-io provides both a Server and a Client.

  • Server: Receives connections from charging stations. Connects to Express, Fastify, NestJS, etc.
  • Client: Connects to a Central System (CSMS). Runs standalone or inside a simulator.

Server Integration

You can attach OCPPServer to any Node.js HTTP server to share the same port as your API.

With Express

import express from "express";
import { createServer } from "http";
import { OCPPServer } from "ocpp-ws-io";

const app = express();
const httpServer = createServer(app);

const ocppServer = new OCPPServer({ protocols: ["ocpp1.6"] });

// 'server' option handles the 'upgrade' event automatically
await ocppServer.listen(0, undefined, { server: httpServer });

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

httpServer.listen(3000, () => {
  console.log("Express + OCPP on port 3000");
});

With Fastify

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

const app = Fastify();
const ocppServer = new OCPPServer({ protocols: ["ocpp2.0.1"] });

app.ready().then(async () => {
  // Attach to the underlying specific Node.js HTTP server
  await ocppServer.listen(0, undefined, { server: app.server });
});

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

await app.listen({ port: 3000 });

With Hono (Node.js)

Hono is a fast, lightweight, web-standard framework. When using the Node.js adapter, you can attach ocpp-ws-io easily.

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { OCPPServer } from "ocpp-ws-io";

const app = new Hono();

// Your standard API routes
app.get("/", (c) => c.text("Hello OCPP"));

const ocppServer = new OCPPServer({ protocols: ["ocpp1.6"] });

// Start Hono server
const server = serve({
  fetch: app.fetch,
  port: 3000,
});

// Attach OCPP WebSocket handling to the Hono Node.js server
// This allows both API and WebSocket to share port 3000
ocppServer.listen(0, undefined, { server });

console.log("Hono + OCPP running on port 3000");

With Koa

import Koa from "koa";
import { createServer } from "http";
import { OCPPServer } from "ocpp-ws-io";

const app = new Koa();
const httpServer = createServer(app.callback());

const ocppServer = new OCPPServer({ protocols: ["ocpp1.6"] });

// Attach to the shared HTTP server
ocppServer.listen(0, undefined, { server: httpServer });

httpServer.listen(3000, () => {
  console.log("Koa + OCPP running on port 3000");
});

With NestJS

ocpp-ws-io can be easily integrated into a NestJS application.

import {
  Module,
  OnModuleInit,
  OnModuleDestroy,
  Injectable,
} from "@nestjs/common";
import { HttpAdapterHost } from "@nestjs/core";
import { OCPPServer } from "ocpp-ws-io";

@Injectable()
export class OCPPGateway implements OnModuleInit, OnModuleDestroy {
  private server: OCPPServer;

  constructor(private readonly adapterHost: HttpAdapterHost) {
    this.server = new OCPPServer({ protocols: ["ocpp1.6", "ocpp2.0.1"] });
  }

  async onModuleInit() {
    // Wait for the HTTP adapter to be ready
    const httpServer = this.adapterHost.httpAdapter.getHttpServer();

    // Attach to the NestJS HTTP server
    await this.server.listen(0, undefined, { server: httpServer });

    this.server.on("client", (client) => {
      console.log(`Client connected: ${client.identity}`);

      client.handle("BootNotification", async ({ params }) => {
        return {
          status: "Accepted",
          currentTime: new Date().toISOString(),
          interval: 300,
        };
      });
    });
  }

  async onModuleDestroy() {
    await this.server.close();
  }
}

@Module({
  providers: [OCPPGateway],
})
export class AppModule {}

Standalone

If you don't need a framework, ocpp-ws-io can create its own WebSocket server:

const server = new OCPPServer({ protocols: ["ocpp1.6"] });
await server.listen(3000);
console.log("Listening on ws://localhost:3000");

Manual Upgrade Handling

For maximum control, use the handleUpgrade getter directly. This is useful if you have complex upgrade logic or routing.

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

const httpServer = createServer();
const ocppServer = new OCPPServer({ protocols: ["ocpp1.6"] });

// Get the upgrade handler
const upgradeHandler = ocppServer.handleUpgrade;

httpServer.on("upgrade", (req, socket, head) => {
  if (req.url?.startsWith("/ocpp")) {
    upgradeHandler(req, socket, head);
  } else {
    socket.destroy();
  }
});

httpServer.listen(3000);

Client Integration

The OCPPClient is typically used to build Charging Stations, Simulators, or Bridges.

Standalone Client

The most common way to run a client is as a standalone background service.

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

const client = new OCPPClient({
  identity: "CS-001",
  endpoint: "ws://localhost:3000",
  protocols: ["ocpp1.6"],
});

client.on("connect", () => {
  console.log("Connected to CSMS");

  // Send BootNotification
  client.call("BootNotification", {
    chargePointVendor: "Tesla",
    chargePointModel: "Model 3",
  });
});

client.connect();

Controlled Simulator (Client + API)

You can run an OCPPClient inside an API server (like Express/Fastify) to build a controllable simulator. This allows you to trigger OCPP messages via HTTP.

import express from "express";
import { OCPPClient } from "ocpp-ws-io";

// 1. Create the simulated charging station
const client = new OCPPClient({
  identity: "SIM-001",
  endpoint: "ws://localhost:9000", // connects to real CSMS
  protocols: ["ocpp1.6"],
});
client.connect();

// 2. Create a control API
const app = express();
app.use(express.json());

// POST /trigger/boot -> Sends BootNotification to CSMS
app.post("/trigger/boot", async (req, res) => {
  try {
    const response = await client.call("BootNotification", {
      chargePointVendor: "Simulator",
      chargePointModel: "v1",
      ...req.body,
    });
    res.json(response);
  } catch (err) {
    res.status(500).json(err);
  }
});

app.listen(3000, () => console.log("Simulator API running on 3000"));

Full-Stack Frameworks

Next.js

✅ Supported: Server Actions & API Routes (Backend)

You CAN use OCPPClient and OCPPServer in Next.js API Routes and Server Actions because they run in the Node.js runtime.

// app/api/trigger/route.ts
import { NextResponse } from "next/server";
import { OCPPClient } from "ocpp-ws-io";

export async function POST() {
  const client = new OCPPClient({
    identity: "NextJS-Client",
    endpoint: "ws://localhost:3000",
    protocols: ["ocpp1.6"],
  });

  await client.connect();

  const response = await client.call("BootNotification", {
    chargePointVendor: "NextJS",
    chargePointModel: "backend",
  });

  await client.close();

  return NextResponse.json(response);
}

✅ Supported: Client Components (Browser)

You CAN use BrowserOCPPClient from ocpp-ws-io/browser in React Client Components and browser scripts. It uses the native browser WebSocket API with zero Node.js dependencies.

"use client";
import { BrowserOCPPClient } from "ocpp-ws-io/browser";

const client = new BrowserOCPPClient({
  identity: "CP001",
  endpoint: "wss://csms.example.com/ocpp",
  protocols: ["ocpp1.6"],
});

await client.connect();

const res = await client.call("ocpp1.6", "BootNotification", {
  chargePointVendor: "NextJS",
  chargePointModel: "frontend",
});

Note: The Node.js OCPPClient from "ocpp-ws-io" still cannot be imported in client components — it depends on ws, node:crypto, and node:events. Use BrowserOCPPClient from "ocpp-ws-io/browser" for browser environments.

See Browser Client for the full API reference and framework integration examples.

On this page