API Reference
Detailed API reference for OCPPClient and OCPPServer.
OCPPClient
import { OCPPClient } from "ocpp-ws-io";Constructor
const client = new OCPPClient(options: ClientOptions);ClientOptions
| Option | Type | Default | Description |
|---|---|---|---|
identity | string | required | Charging station ID |
endpoint | string | required | WebSocket URL (ws:// or wss://) |
protocols | string[] | [] | OCPP subprotocols to negotiate |
securityProfile | SecurityProfile | NONE | Security profile (0–3) |
password | string | Buffer | — | Password for Basic Auth (Profile 1 & 2) |
tls | TLSOptions | — | TLS/SSL options (Profile 2 & 3) |
headers | Record<string, string> | — | Additional WebSocket headers |
query | Record<string, string> | — | Additional URL query parameters |
reconnect | boolean | true | Auto-reconnect on disconnect |
maxReconnects | number | Infinity | Max reconnection attempts |
pingIntervalMs | number | 30000 | Includes ±25% randomized jitter |
strictMode | boolean | string[] | false | Enable/restrict schema validation |
strictModeMethods | string[] | — | Restrict validation to specific methods |
logging | LoggingConfig | {} | Configuration for structured logging. |
offlineQueue | boolean | false | Queue calls while disconnected, flush on reconnect. |
offlineQueueMaxSize | number | 100 | Max offline queue size before oldest are dropped. |
compression | boolean | CompressionOptions | false | Enable WebSocket permessage-deflate compression. |
LoggingConfig
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable or disable all logging. |
level | string | 'info' | Minimum log level (trace, debug, info, warn, error, fatal). |
prettify | boolean | false | Use prettyTransport for human-readable output (colors, icons). |
exchangeLog | boolean | false | Log all OCPP messages with direction (IN/OUT) and metadata. |
logger | LoggerLike | undefined | Custom logger instance (e.g., Pino) to replace the default logger. |
handler | function | undefined | Custom voltlog-io transport function (entry) => void | Promise<void> |
showMetadata | boolean | true | Show trailing metadata object in logs. |
showSourceMeta | boolean | true | Show source context (component, identity). |
prettifySource | boolean | false | Compact source tag [OCPPServer/CP-1]. |
prettifyMetadata | boolean | false | Format metadata as key=value pairs. |
Methods
connect()
Connect to the OCPP server.
await client.connect();call(protocol?, method, params, options?)
Make an RPC call. Throws a TimeoutError or protocol-level Error if the request fails.
Make an RPC call. Throws a TimeoutError or protocol-level Error if the request fails.
protocol: Optional. e.g., "ocpp1.6". If omitted, generic type inference is used.method: The OCPP method name (e.g., "BootNotification").params: The request payload.options:{ timeoutMs?: number, retries?: number, idempotencyKey?: string }
// With manual idempotency key to prevent double execution on reconnections
const result = await client.call("ocpp1.6", "BootNotification", { ... }, { idempotencyKey: "unique-boot-123" });safeCall(protocol?, method, params, options?)
Exactly like call(), except it catches all errors and returns the response payload on success, or undefined on error rather than throwing. Useful for fire-and-forget or localized error handling without breaking loops.
const result = await client.safeCall(
"ocpp1.6",
"ClearCache",
{},
{ timeoutMs: 15000 },
);
if (result === undefined) {
client.logger.warn("Station failed to clear cache", { error });
}handle(protocol?, method, handler)
Register an RPC handler.
protocol: Optional. If provided, handler only triggers for this protocol version.method: The OCPP method name.handler:(context) => Response | Promise<Response>
// Version specific
client.handle("ocpp1.6", "Reset", ({ params }) => { ... });
// Generic
client.handle("Reset", ({ params }) => { ... });
// Catch-all
client.handle((method, { params }) => { ... });close(options?)
Close the connection gracefully or forcefully.
By default, calling close() will wait for all pending RPC requests to complete before terminating the socket to prevent interrupting in-flight operations.
// Graceful close (waits for pending calls, sends 1000 code)
await client.close({ code: 1000, reason: "Normal Closure" });
// Forceful immediate drop (useful during DDoS or severe errors)
await client.close({ force: true });
// Graceful WS close, but skips waiting for pending asynchronous RPC calls
await client.close({ awaitPending: false });Properties
logger
A fully initialized voltlog-io instance localized to this client. Automatically includes the client identity and component: "OCPPClient" in the context of every log message.
client.logger.info("Initializing updates", { pendingFiles: 4 });OCPPServer
import { OCPPServer } from "ocpp-ws-io";Constructor
const server = new OCPPServer(options?: ServerOptions);ServerOptions
| Option | Type | Default | Description |
|---|---|---|---|
protocols | string[] | [] | Accepted OCPP subprotocols |
securityProfile | SecurityProfile | NONE | Security profile |
handshakeTimeoutMs | number | 30000 | Timeout for WebSocket handshake (ms) |
tls | TLSOptions | — | TLS options (Profile 2 & 3) |
logging | LoggingConfig | {} | Configuration for structured logging. |
sessionTtlMs | number | 7200000 | Garbage collection inactivity timeout |
rateLimit | RateLimitOptions | — | Token bucket socket & method limiter |
healthEndpoint | boolean | false | Expose HTTP /health and /metrics |
maxPayloadBytes | number | 65536 | Max WebSocket frame size in bytes. Rejects oversized messages at the transport layer before any parsing. Prevents OOM from malicious payloads. |
workerThreads | boolean | object | false | Enable worker thread pool for JSON parsing. true = auto pool size, { poolSize, maxQueueSize } for fine-tuning. |
compression | boolean | CompressionOptions | false | Enable WebSocket permessage-deflate compression. true = sensible defaults (threshold: 1024, level: 6). |
CompressionOptions
| Option | Type | Default | Description |
|---|---|---|---|
threshold | number | 1024 | Minimum payload size (bytes) to compress. |
level | number | 6 | zlib compression level (1=fastest, 9=smallest). |
memLevel | number | 8 | zlib memory level (1–9). |
serverNoContextTakeover | boolean | true | Don't retain server deflate context (saves ~120KB/conn). |
clientNoContextTakeover | boolean | true | Don't retain client deflate context. |
RateLimitOptions
| Option | Type | Default | Description |
|---|---|---|---|
limit | number | — | Max messages allowed globally per window |
windowMs | number | — | Time window in milliseconds |
onLimitExceeded | "ignore" | "disconnect" | function | "ignore" | Action to execute when limit is breached |
methods | Record<string, { limit; windowMs }> | — | Deep method-wise limits (e.g. Heartbeat) |
CORSOptions
| Option | Type | Default | Description |
|---|---|---|---|
allowedOrigins | string[] | — | Origins allowed to connect via WebSocket |
allowedIPs | string[] | — | Exact IPv4/v6 or CIDR IP ranges (e.g. /24) |
allowedSchemes | ("ws" | "wss")[] | — | Restrict connections to specific protocols |
Methods
listen(port, host?, options?)
Start listening on a port. Returns the http.Server instance.
auth(handler)
Attach authentication logic.
server.auth((ctx) => {
// ctx.handshake has .identity, .pathname, .headers, etc.
ctx.accept({ session: { ... } }); // Attach session data to client
});cors(options)
Apply CORS rules directly to the server or router levels. This protects endpoints from unauthorized WebSocket hijacking or public IP access.
server.cors({
allowedOrigins: ["https://dashboard.example.com"],
allowedIPs: ["192.168.1.0/24", "10.0.0.5"],
allowedSchemes: ["wss"],
});on("client", handler)
Listen for new connections.
server.on("client", (client) => {
// client is an OCPPServerClient (extends OCPPClient)
console.log(client.session); // Access session data
});updateTLS(options)
Hot-reload TLS certificates on all active HTTPS servers without dropping connections.
Only valid when using SecurityProfile.TLS_BASIC_AUTH or TLS_CLIENT_CERT.
server.updateTLS({
cert: fs.readFileSync("./certs/server.crt"),
key: fs.readFileSync("./certs/server.key"),
});See TLS Certificate Hot-Reload for full details.
on("securityEvent", handler)
Emitted for every security-relevant action. Useful for SIEM, alerting, and audit logging.
server.on("securityEvent", (event) => {
// event.type: "AUTH_FAILED" | "CONNECTION_RATE_LIMIT" | "UPGRADE_ABORTED"
siem.log(event);
});See Security Event Monitoring for full details.
sendToClient(identity, protocol?, method, params, options?)
Helper method to dispatch an outgoing RPC call to a specific connected client by its identity. Throws an error if the station is not connected. Matches the client.call() signature and supports timeoutMs in the options argument.
const result = await server.sendToClient(
"CP-001",
"ocpp1.6",
"Reset",
{
type: "Soft",
},
{ timeoutMs: 10000 },
);safeSendToClient(identity, protocol?, method, params, options?)
Exactly like sendToClient(), but catches errors (and disconnected station errors), returning the response payload on success, or undefined on error. Highly recommended for bulk operations across your cluster where individual failures shouldn't throw exceptions.
const result = await server.safeSendToClient(
"CP-001",
"ocpp1.6",
"UpdateFirmware",
{ location: "..." },
{ timeoutMs: 30000 },
);
if (result !== undefined) {
console.log("Firmware update accepted");
}broadcastBatch(identities, method, params, options?)
Broadcast an identical RPC call to many stations concurrently. For clustered architectures, unicast commands are grouped and dispatched in pipeline batches via the adapter's streams, reducing per-message TCP round-trip overhead.
const targets = ["CP-001", "CP-002", "CP-003", ...thousands];
await server.broadcastBatch(targets, "Reset", { type: "Hard" });stats()
Returns instantaneous observability metrics about the server's local node status. This is deeply integrated with standard Node.js internals to supply immediate health checks for Prometheus and Loki collection.
const telemetry = server.stats();
console.log(`Active Managed Sessions: ${telemetry.activeSessions}`);
console.log(`Active Raw WebSockets: ${telemetry.webSockets?.total}`);
console.log(
`Pending Network Flushes: ${telemetry.webSockets?.bufferedAmount} bytes`,
);
console.log(`Memory Used: ${telemetry.memoryUsage.heapUsed} bytes`);
console.log(`Uptime: ${telemetry.uptimeSeconds}s`);
console.log(`PID: ${telemetry.pid}`);adapterMetrics()
Fetches deep backend observability from the underlying clustering adapter. When using the RedisAdapter, this returns the consumerLag (pending unread stream messages) specific to this node, enabling DevOps to perform accurate horizontal capacity auto-scaling.
const metrics = await server.adapterMetrics();
console.log("Redis Backlog:", metrics?.redisConsumerLag?.pendingMessages);Properties
logger
An initialized voltlog-io logger isolated to the Server context (via component: "OCPPServer"). Automatically utilized by the internal router and exchange logs.
server.logger.warn("Unrecognized protocol attempted", { requested: "ocpp1.5" });Protocol Constants
NOREPLY
Return NOREPLY from a handler to suppress the automatic response. This is useful for asynchronous processing where you might send a response later manually, or for specific OCPP flows.
import { NOREPLY } from "ocpp-ws-io";
client.handle("StatusNotification", ({ params }) => {
// Process the notification but don't send a response immediately
return NOREPLY;
});BrowserOCPPClient
import { BrowserOCPPClient } from "ocpp-ws-io/browser";A browser-compatible OCPP client with the same typed API as OCPPClient. Uses the native browser WebSocket API — no Node.js dependencies.
See Browser Client for the full guide with examples. See Browser Client for the full guide with examples.
Constructor
const client = new BrowserOCPPClient(options: BrowserClientOptions);BrowserClientOptions
| Option | Type | Default | Description |
|---|---|---|---|
identity | string | required | Charging station ID |
endpoint | string | required | WebSocket URL (ws:// or wss://) |
protocols | string[] | [] | OCPP subprotocols to negotiate |
query | Record<string, string> | — | Additional URL query parameters |
reconnect | boolean | true | Auto-reconnect on disconnect |
maxReconnects | number | Infinity | Max reconnection attempts |
backoffMin | number | 1000 | Initial reconnect delay (ms) |
backoffMax | number | 30000 | Maximum reconnect delay (ms) |
callTimeoutMs | number | 30000 | Default RPC call timeout (ms) |
callConcurrency | number | 1 | Max concurrent outbound calls |
maxBadMessages | number | Infinity | Close after N bad messages |
respondWithDetailedErrors | boolean | false | Include error details in responses |
logging | LoggingConfig | {} | Configuration for structured logging. |
| Option | Type | Default | Description |
| :-------------------------- | :----------------------- | :--------- | :------------------------------------ |
identity | string | required | Charging station ID |
endpoint | string | required | WebSocket URL (ws:// or wss://) |
protocols | string[] | [] | OCPP subprotocols to negotiate |
query | Record<string, string> | — | Additional URL query parameters |
reconnect | boolean | true | Auto-reconnect on disconnect |
maxReconnects | number | Infinity | Max reconnection attempts |
backoffMin | number | 1000 | Initial reconnect delay (ms) |
backoffMax | number | 30000 | Maximum reconnect delay (ms) |
callTimeoutMs | number | 30000 | Default RPC call timeout (ms) |
callConcurrency | number | 1 | Max concurrent outbound calls |
maxBadMessages | number | Infinity | Close after N bad messages |
respondWithDetailedErrors | boolean | false | Include error details in responses |
logging | LoggingConfig | {} | Configuration for structured logging. |
Methods
All methods match OCPPClient:
await client.connect();
// Version-aware typed call
const result = await client.call("ocpp1.6", "BootNotification", { ... });
const { success } = await client.safeCall("ocpp1.6", "Heartbeat", {});
const { success } = await client.safeCall("ocpp1.6", "Heartbeat", {});
// Register handlers (version-specific, generic, wildcard)
client.handle("ocpp1.6", "Reset", ({ params }) => { ... });
client.handle("Reset", ({ params }) => { ... });
client.handle((method, { params }) => { ... });
// Close
await client.close();
await client.close({ force: true });
await client.close({ awaitPending: true });
// Runtime reconfiguration
client.reconfigure({ callTimeoutMs: 10000 });
// Handler removal
client.removeHandler("Reset");
client.removeHandler("ocpp1.6", "Reset");
client.removeAllHandlers();
// Raw message
client.sendRaw(JSON.stringify([2, "uuid", "Heartbeat", {}]));Properties
logger
A fully initialized logger specific to the browser console. Works with browser contexts.
client.logger.info("Retrying connection...");Properties
logger
A fully initialized logger specific to the browser console. Works with browser contexts.
client.logger.info("Retrying connection...");Events
client.on("open", (event) => {
/* connected */
});
client.on("close", ({ code, reason }) => {
/* disconnected */
});
client.on("error", (error) => {
/* error */
});
client.on("connecting", ({ url }) => {
/* attempting */
});
client.on("reconnect", ({ attempt, delay }) => {
/* reconnecting */
});
client.on("message", (message) => {
/* OCPP message */
});
client.on("call", (call) => {
/* incoming call */
});
client.on("callResult", (result) => {
/* result received */
});
client.on("callError", (error) => {
/* error received */
});
client.on("badMessage", ({ message, error }) => {
/* malformed */
});Error Classes
All error classes are exported for instanceof checks:
import {
// Base errors
TimeoutError, // Call timeout
UnexpectedHttpResponse, // Non-101 upgrade response
WebsocketUpgradeError, // WebSocket upgrade failure
// RPC errors (OCPP-J spec Section 4.3)
RPCGenericError,
RPCNotImplementedError,
RPCNotSupportedError,
RPCInternalError,
RPCProtocolError,
RPCSecurityError,
RPCFormationViolationError,
RPCPropertyConstraintViolationError,
RPCOccurrenceConstraintViolationError,
RPCTypeConstraintViolationError,
RPCGenericTransportError,
} from "ocpp-ws-io";