Introducing ocpp-ws-io: The Type-Safe OCPP Ecosystem for Node.js ⚡
Source: Dev.to

Overview
If you’ve ever built software for the EV (Electric Vehicle) charging industry, you know that the Open Charge Point Protocol (OCPP) is the undisputed standard for communication between Charge Points and Central Systems (CSMS).
But building a scalable, reliable, and secure OCPP‑compliant system is notoriously difficult. Developers often struggle with guessing payload shapes, manually validating JSON schemas, implementing complex WebSocket framing, and handling connection drops.
That’s why I built ocpp-ws-io—a type‑safe, production‑ready OCPP WebSocket RPC client and server ecosystem for Node.js, built from the ground up with TypeScript.
🚀 Why another OCPP library?
Building a CSMS or a charge‑point simulator shouldn’t require hand‑writing validation logic or risking runtime errors from malformed payloads. ocpp-ws-io solves these problems by providing:
- 🎯 End‑to‑End Type Safety: Fully auto‑generated TypeScript types covering all OCPP 1.6, 2.0.1, and 2.1 methods. No more guessing what a
BootNotificationpayload should look like. - 📐 Strict Schema Validation: Optional strict mode with built‑in JSON‑schema validation before your business logic even touches the message.
- 🛜 Router Built‑In: An Express/Hono‑style router for modular, clean code and easy management.
- 🔒 Comprehensive Security: Out‑of‑the‑box support for OCA Security Profiles 0–3 (Plain WS, Basic Auth, TLS + Basic Auth, and Mutual TLS).
- 🚦 DDoS Protection & Rate Limiting: Socket‑layer token‑bucket rate limiting per station and method.
- 🔁 Resilience: Exponential‑backoff auto‑reconnect, Redis state‑synchronisation, and Idempotency Keys to guarantee exactly‑once message delivery on retries.
- 🧩 Framework‑Agnostic: Use it standalone or plug it seamlessly into Express, Fastify, NestJS, or any custom HTTP server.
- 📡 Built for Scale: Redis adapter for multi‑instance deployments with durable message delivery via Streams.
💻 Code Speaks Louder Than Words
The Server (CSMS)
import { OCPPServer } from "ocpp-ws-io";
const server = new OCPPServer({
protocols: ["ocpp1.6", "ocpp2.0.1"],
logging: { prettify: true, exchangeLog: true, level: "info" }, // Powered by voltlog-io!
});
// Authenticate incoming connections
server.auth((ctx) => {
console.log(`Connection attempt from ${ctx.handshake.identity}`);
ctx.accept({ session: { authorized: true } });
});
server.on("client", (client) => {
console.log(`${client.identity} connected via ${client.protocol}`);
// Type‑safe RPC handler
client.handle("ocpp1.6", "BootNotification", ({ params }) => ({
status: "Accepted",
currentTime: new Date().toISOString(),
interval: 300,
}));
});
await server.listen(3000);
console.log("⚡ OCPP Server running on port 3000");
The Client (Charge Point 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,
});
// Handle commands from the central system
client.handle("Reset", ({ params }) => {
console.log("CSMS requested a Reset of type:", params.type);
return { status: "Accepted" };
});
await client.connect();
// Send an RPC request and await the result!
const response = await client.call("ocpp1.6", "BootNotification", {
chargePointVendor: "VendorX",
chargePointModel: "ModelY",
});
console.log("Central System response status:", response.status); // Type‑checked!
🛜 Express‑Style Routing & Middleware
One of the standout features of ocpp-ws-io is its robust Routing and Middleware system, designed to feel exactly like Express or Hono. This allows you to build modular, clean, and highly manageable CSMS architectures.
You can intercept HTTP Upgrade requests (Connection Phase), as well as incoming/outgoing OCPP RPC messages (Message Phase).
import { OCPPServer, defineMiddleware } from "ocpp-ws-io";
const server = new OCPPServer({ protocols: ["ocpp1.6"] });
// 1️⃣ Connection middleware: block bad IPs or rate‑limit before WebSockets even open!
const rateLimiter = defineMiddleware(async (ctx, next) => {
if (isRateLimited(ctx.handshake.remoteAddress)) {
ctx.reject(429, "Too Many Requests"); // Instantly drops the connection
} else {
await next();
}
});
server.use(rateLimiter);
// 2️⃣ Create dynamic routes with wildcard parameter extraction
const chargerRoute = server.route("/api/v1/chargers/:id");
chargerRoute.on("client", (client) => {
console.log(`Charger connected at endpoint: ${client.handshake.pathname}`);
// 3️⃣ Message middleware: log processing times for every single RPC call
client.use(async (ctx, next) => {
const start = Date.now();
await next();
console.log(`[${ctx.action}] took ${Date.now() - start}ms`);
});
client.handle("BootNotification", ({ params }) => ({
status: "Accepted",
currentTime: new Date().toISOString(),
interval: 300,
}));
});
await server.listen(3000);
For more advanced routing scenarios, see the documentation: https://ocpp-ws-io.rohittiwari.me/docs/routing
🪵 First‑Class Structured Logging (voltlog-io)
High‑throughput WebSocket environments are a nightmare to debug with standard console.log. That’s why ocpp-ws-io includes built‑in structured JSON logging powered by voltlog‑io.
With a single config toggle you get:
- Extremely fast JSON logging for production.
- Beautiful, colour‑coded output with latency metrics for local development (
prettify: true).
Exchange Logs (exchangeLog: true) perfectly trace every inbound ([IN]) and outbound ([OUT]) OCPP command.
⚡ CP-101 → BootNotification [OUT]
✅ CP-101 ← BootNotification [IN] { latencyMs: 45 }
🌐 The Browser Client
Need to build a Web UI, CSMS dashboard, or testing interface that talks directly to chargers or proxies? We also ship a zero‑dependency Browser Client (ocpp-ws-io/browser) that runs flawlessly in vanilla JS, React, Vue, or Svelte. All the strict type safety from the server is available right in your browser!
🛠️ The ocpp-ws-cli Ecosystem
A library without great developer tools is only half the battle. Along with the core ocpp-ws-io package we released ocpp-ws-cli – the ultimate CLI for OCPP developers.
Available instantly via npx ocpp-ws-cli, this toolkit completely transforms how you build and test your backend:
- 🎮
ocpp simulate– Virtual Charge Point with an interactive terminal UI (boot sequence, heartbeat, live voltage/current/power, plug‑ins, RFID, fault states). - 📡
ocpp mock– SSE mock server that streams dummyMeterValues,StatusNotification,Heartbeatdata for frontend development. - 🚄
ocpp bench– Throughput and latency benchmarking engine with percentile metrics and live dashboard. - 💣
ocpp load-test– Distributed load engine simulating thousands of simultaneous charge‑point connections. - 👾
ocpp fuzz– Protocol chaos engine that floods your CSMS with malformed JSON payloads to test strict‑mode handling. - 🔐
ocpp certs– Auto‑generate 4096‑bit root CAs and signed server/client.pemcertificates for OCA Profile 2 & 3 testing. - 🗂️
ocpp audit– Security wizard that runs automated tests and produces a markdown roadmap (audit‑report.md). - 📝
ocpp generate– Convert custom.jsonschemas into.d.tsdeclaration libraries for 100 % type safety. - 🧪
ocpp test– Execute modularised OCTT compliance test suites directly against your server.
🌟 Get Involved
The EV infrastructure ecosystem is growing rapidly, and robust open‑source tools will be the backbone of that growth. Whether you are building the next big CSMS platform, an EV charging app, or just learning about the industry, give ocpp-ws-io a try!
We are actively looking for feedback, issues, and pull requests. Let us know what you think in the comments below. Happy charging! ⚡🚗
