OCPP WS UI
Framework Integration
Integrate ocpp-ws-board with Express, Hono, or NestJS using built-in adapters.
Framework Integration
ocpp-ws-board provides first-class adapters for popular Node.js frameworks. Choose the one that matches your backend.
Express / Connect
Installation
npm install express ocpp-ws-boardBasic Setup
import express from "express";
import { OCPPServer } from "ocpp-ws-io";
import { expressAdapter } from "ocpp-ws-board";
const app = express();
const server = new OCPPServer({ protocols: ["ocpp1.6"] });
// Create board with Express adapter
const { handler, plugin } = expressAdapter({
auth: { mode: "token", token: "secret" },
});
// Attach plugin to OCPP server
server.plugin(plugin);
// Mount board at /board path
app.use("/board", handler);
// Start servers
server.listen(5000);
app.listen(9000, () => {
console.log("Dashboard: http://localhost:9000/board");
});Complete Express Application
import express from "express";
import { OCPPServer } from "ocpp-ws-io";
import { expressAdapter } from "ocpp-ws-board";
const app = express();
const server = new OCPPServer({ protocols: ["ocpp1.6", "ocpp2.0.1"] });
// Create dashboard
const { handler, plugin } = expressAdapter({
auth: { mode: "credentials", username: "admin", password: "pass" },
store: {
maxMessages: 10000,
maxProxyEvents: 2000,
},
});
// Connect to OCPP server
server.plugin(plugin);
// OCPP routes
server.route("/ocpp/:identity").on("client", (client) => {
console.log(`Charger connected: ${client.identity}`);
client.handle("ocpp1.6", "BootNotification", async (ctx) => {
return {
currentTime: new Date().toISOString(),
interval: 300,
status: "Accepted",
};
});
client.handle("ocpp1.6", "Heartbeat", () => ({
currentTime: new Date().toISOString(),
}));
});
// Express routes
app.use(express.json());
app.use("/board", handler);
app.get("/health", (req, res) => {
res.json({ status: "ok" });
});
// Start servers
server.listen(5000);
app.listen(9000, () => {
console.log("✅ OCPP Server: ws://localhost:5000");
console.log("✅ Dashboard: http://localhost:9000/board");
});Hono
Installation
npm install hono ocpp-ws-boardBasic Setup
import { Hono } from "hono";
import { OCPPServer } from "ocpp-ws-io";
import { honoAdapter } from "ocpp-ws-board";
const app = new Hono();
const server = new OCPPServer({ protocols: ["ocpp1.6"] });
// Create board with Hono adapter
const { subApp, plugin } = honoAdapter({
auth: { mode: "token", token: "secret" },
});
// Attach plugin
server.plugin(plugin);
// Mount at /board
app.route("/board", subApp);
// Start servers
server.listen(5000);
Bun.serve({ fetch: app.fetch, port: 9000 });
console.log("Dashboard: http://localhost:9000/board");Complete Hono Application
import { Hono } from "hono";
import { cors } from "hono/cors";
import { OCPPServer } from "ocpp-ws-io";
import { honoAdapter } from "ocpp-ws-board";
const app = new Hono();
const server = new OCPPServer({ protocols: ["ocpp1.6", "ocpp2.0.1"] });
// CORS for dashboard
app.use("/*", cors({
origin: ["http://localhost:9000"],
credentials: true,
}));
// Create dashboard
const { subApp, plugin } = honoAdapter({
auth: { mode: "token", token: process.env.DASHBOARD_TOKEN! },
sseHeartbeatMs: 15000,
});
server.plugin(plugin);
// OCPP routes
server.route("/api/v2/chargers/*").on("client", (client) => {
client.handle("ocpp2.0.1", "BootNotification", async (ctx) => {
return {
currentTime: new Date().toISOString(),
interval: 300,
status: "Accepted",
};
});
});
// Mount dashboard
app.route("/board", subApp);
// Health check
app.get("/health", (c) => c.json({ status: "ok" }));
// Start
server.listen(5000);
Bun.serve({ fetch: app.fetch, port: 9000 });NestJS
Installation
npm install @nestjs/common @nestjs/core ocpp-ws-boardBasic Setup
import { Module } from "@nestjs/common";
import { BoardModule } from "ocpp-ws-board/nest";
@Module({
imports: [
BoardModule.register({
auth: { mode: "token", token: "secret" },
}),
],
})
export class AppModule {}Advanced Configuration
import { Module } from "@nestjs/common";
import { BoardModule } from "ocpp-ws-board/nest";
@Module({
imports: [
BoardModule.registerAsync({
useFactory: () => ({
auth: {
mode: "custom",
validate: async (creds) => {
// Custom validation
return { name: "admin" };
},
},
store: {
maxMessages: 10000,
maxProxyEvents: 2000,
},
}),
inject: [],
}),
],
})
export class AppModule {}Complete NestJS Application
// app.module.ts
import { Module } from "@nestjs/common";
import { OCPPModule } from "./ocpp.module";
import { BoardModule } from "ocpp-ws-board/nest";
@Module({
imports: [
OCPPModule,
BoardModule.register({
auth: { mode: "token", token: process.env.DASHBOARD_TOKEN! },
}),
],
})
export class AppModule {}
// ocpp.module.ts
import { Module, OnModuleInit, Inject } from "@nestjs/common";
import { OCPPServer } from "ocpp-ws-io";
import { BOARD_PLUGIN } from "ocpp-ws-board/nest";
@Module({})
export class OCPPModule implements OnModuleInit {
@Inject(BOARD_PLUGIN)
private boardPlugin: any;
async onModuleInit() {
const server = new OCPPServer({ protocols: ["ocpp1.6"] });
// Attach board plugin
server.plugin(this.boardPlugin);
// Your OCPP routes
server.route("/ocpp/:identity").on("client", (client) => {
client.handle("ocpp1.6", "BootNotification", () => ({
currentTime: new Date().toISOString(),
interval: 300,
status: "Accepted",
}));
});
await server.listen(5000);
console.log("✅ OCPP Server running on :5000");
}
}Using the Main createBoard Function
If you prefer not to use adapters, you can use the createBoard() function directly:
import { createBoard } from "ocpp-ws-board";
const board = createBoard({
auth: { mode: "token", token: "secret" },
});
// Returns:
// - board.app: Hono app (REST API + static files)
// - board.plugin: OCPP plugin
// - board.store: In-memory store
// - board.cleanup(): Cleanup functionManual Mounting
// With Express
import { createNodeMiddleware } from "@hono/node-server";
app.use("/board", createNodeMiddleware(board.app));
// With Fastify
import fastifyHttpProxy from "@fastify/http-proxy";
fastify.register(fastifyHttpProxy, {
upstream: "http://localhost:3001", // board.app port
prefix: "/board",
});Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
auth | BoardAuthConfig | Required | Authentication configuration |
store | StoreOptions | {} | Ring buffer sizes |
sseHeartbeatMs | number | 15000 | SSE keepalive interval |
Store Options
interface StoreOptions {
maxMessages?: number; // Default: 5000
maxProxyEvents?: number; // Default: 1000
maxSmartChargeHistory?: number; // Default: 500
}Next Steps
- API Reference — Complete REST API documentation
- Architecture — Internal architecture and data flow
- Quick Start — Get started with the dashboard