Profile
Back to NewsBack
GitHub Trending 8 min
Reader Mode
SAP/e-mobility-charging-stations-simulator: OCPP-J charging stations simulator

SAP/e-mobility-charging-stations-simulator: OCPP-J charging stations simulator

17 hours ago

Simple node.js software to simulate and scale a set of charging stations based on the OCPP-J protocol as part of SAP e-Mobility solution.

Table of contents

- Prerequisites - Windows - macOS - GNU/Linux - Development prerequisites (optional) - Unix - Windows - Branching model - Dependencies - Charging stations simulator configuration - Charging station template configuration - Charging station configuration - Version 1.6 - Version 2.0.x - Version 1.6 - Version 2.0.x - MCP Protocol - WebSocket Protocol - HTTP Protocol (deprecated)

Installation

Prerequisites

Install the node.js current LTS or superior version runtime environment:

Windows

choco install -y nodejs

macOS

brew install node

GNU/Linux

  • NodeSource node.js binary distributions for all supported versions.

Development prerequisites (optional)

Install mise for managing automatically the node.js runtime and package manager version:

Unix

curl -fsSL https://mise.run | sh

Windows

winget install jdx.mise

Then activate mise in your shell and run mise install from the repository root to install the development tools.

Branching model

The main branch is the default development branch. The vX branches are the maintenance branches for the corresponding major version X. The vX.Y branches are the maintenance branches for the corresponding major and minor version X.Y.

Dependencies

From the repository root, enable Corepack and install the pnpm version declared in package.json if mise is not installed and configured. If Corepack is not available, install it with npm install --global corepack first.

corepack enable
corepack install

In the repository root, run the following command:

pnpm install

Initial configuration

Copy the configuration template file src/assets/config-template.json to src/assets/config.json. Copy the RFID tags template file src/assets/idtags-template.json to src/assets/idtags.json.

Tweak them to your needs by following the section configuration files syntax: OCPP server supervision URL(s), charging station templates, etc.

Start simulator

pnpm start

Start Web UI

See Web UI README.md for more information.

Start CLI

See CLI README.md for more information.

Configuration files syntax

All configuration files are using the JSON standard syntax.

Configuration files locations:

The charging stations simulator's configuration parameters must be within the src/assets/config.json file. A charging station simulator configuration template file is available at src/assets/config-template.json.

All charging station configuration templates are in the directory src/assets/station-templates.

A list of RFID tags must be defined for the automatic transaction generator in a file with the default location and name: src/assets/idtags.json. A template file is available at src/assets/idtags-template.json.

Configuration files hierarchy and priority:

  1. charging station configuration: dist/assets/configurations;
  2. charging station configuration template: src/assets/station-templates;
  3. charging stations simulator configuration: src/assets/config.json.
The charging stations simulator has an automatic configuration files reload feature at change for:
  • charging stations simulator configuration;
  • charging station configuration templates;
  • charging station authorization RFID tags lists.
But the modifications to test have to be done to the files in the build target directory dist/assets. Once the modifications are done, they have to be reported to the matching files in the build source directory src/assets to ensure they will be taken into account at next build.

Charging stations simulator configuration

src/assets/config.json:

| Key | Value(s) | Default Value | Value type | Description | | -------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | $schemaVersion | 1 | 1 | integer | Configuration schema version. Set to 1. Files without this field are migrated from v0; deprecated keys are remapped on every load. | | supervisionUrls | | [] | string \| string[] | string or strings array containing global connection URIs to OCPP-J servers | | supervisionUrlDistribution | round-robin/random/charging-station-affinity | charging-station-affinity | string | supervision urls distribution policy to simulated charging stations | | log | | {
"enabled": true,
"file": "logs/combined.log",
"errorFile": "logs/error.log",
"statisticsInterval": 60,
"level": "info",
"console": false,
"format": "simple",
"rotate": true
} | {
enabled?: boolean;
file?: string;
errorFile?: string;
statisticsInterval?: number;
level?: string;
console?: boolean;
format?: string;
rotate?: boolean;
maxFiles?: string \| number;
maxSize?: string \| number;
} | Log configuration section:
- _enabled_: enable logging
- _file_: log file relative path
- _errorFile_: error log file relative path
- _statisticsInterval_: seconds between charging stations statistics output in the logs
- _level_: emerg/alert/crit/error/warning/notice/info/debug winston logging level
- _console_: output logs on the console
- _format_: winston log format
- _rotate_: enable daily log files rotation
- _maxFiles_: maximum number of log files: https://github.com/winstonjs/winston-daily-rotate-file#options
- _maxSize_: maximum size of log files in bytes, or units of kb, mb, and gb: https://github.com/winstonjs/winston-daily-rotate-file#options | | worker | | {
"processType": "workerSet",
"startDelay": 500,
"elementAddDelay": 0,
"elementsPerWorker": 'auto',
"poolMinSize": 4,
"poolMaxSize": 16
} | {
processType?: WorkerProcessType;
startDelay?: number;
elementAddDelay?: number;
elementsPerWorker?: number \| 'auto' \| 'all';
poolMinSize?: number;
poolMaxSize?: number;
resourceLimits?: ResourceLimits;
} | Worker configuration section:
- _processType_: worker threads process type (workerSet/fixedPool/dynamicPool)
- _startDelay_: milliseconds to wait at worker threads startup (only for workerSet worker threads process type)
- _elementAddDelay_: milliseconds to wait between charging station add
- _elementsPerWorker_: number of charging stations per worker threads for the workerSet process type (auto means (number of stations) / (number of CPUs) \* 1.5 if (number of stations) > (number of CPUs), otherwise 1; all means a unique worker will run all charging stations)
- _poolMinSize_: worker threads pool minimum number of threads
- _poolMaxSize_: worker threads pool maximum number of threads
- _resourceLimits_: worker threads resource limits object option | | uiServer | | {
"enabled": false,
"type": "ws",
"version": "1.1",
"accessPolicy": {
"requireTlsForNonLoopback": true,
"trustedProxies": [],
"allowLoopbackProxy": false,
"allowedHosts": [],
"allowedOrigins": []
},
"options": {
"host": "localhost",
"port": 8080
}
} | {
enabled?: boolean;
type?: ApplicationProtocol;
version?: ApplicationProtocolVersion;
accessPolicy?: {
requireTlsForNonLoopback?: boolean;
trustedProxies?: string[];
allowLoopbackProxy?: boolean;
allowedHosts?: string[];
allowedOrigins?: string[];
};
options?: ServerOptions;
authentication?: {
enabled: boolean;
type: AuthenticationType;
username?: string;
password?: string;
};
metrics?: {
enabled?: boolean;
softSampleCap?: number;
};
securityHeaders?: {
strictTransportSecurity?: string \| false;
};
} | UI server configuration section:
- _enabled_: enable UI server
- _type_: 'ws', 'mcp' or 'http' (deprecated)
- _version_: HTTP version '1.1' or '2.0' (ws and mcp transports only support '1.1')
- _accessPolicy_: gateway access policy. Loopback request sources are allowed in plaintext; non-loopback sources require TLS termination by a reverse proxy:
  - _requireTlsForNonLoopback_: reject non-loopback plaintext requests; the check honors X-Forwarded-Proto or Forwarded: proto= from a trusted proxy, non-loopback requests without forwarded protocol headers are denied as tls-required
  - _trustedProxies_: IPv4 or IPv6 literals of the immediate reverse proxies whose forwarded headers are honored (hostnames and CIDR ranges are not accepted; only single-hop forwarded chains are honored); a compromised entry can bypass per-client rate limiting by varying X-Forwarded-For
  - _allowLoopbackProxy_: accept forwarded headers when the immediate peer is loopback AND listed in _trustedProxies_ (e.g. ['127.0.0.1', '::1'])
  - _allowedHosts_: explicit Host header allowlist; mitigates DNS rebinding when the UI server is exposed through a browser-facing host
  - _allowedOrigins_: explicit Origin header allowlist; when empty, the request Origin's URL hostname falls back to matching against _allowedHosts_
- _options_: node.js net module listen options
- _authentication_: authentication type configuration section
- _metrics_: opt-in Prometheus /metrics endpoint (served on the configured uiServer.type listener — http, ws or mcp):
  - _enabled_: enable the /metrics endpoint
  - _softSampleCap_: soft cardinality cap above which a single warn is logged per scrape (default 5000)
- _securityHeaders_: opt-in security response headers emitted on every UI-server HTTP response path served over secure transport, across the http, ws and mcp transports (denials, WebSocket upgrade rejections, http success responses and the /metrics endpoint), except MCP JSON-RPC success bodies (written by the MCP SDK transport); absent by default so the default response behavior is unchanged:
  - _strictTransportSecurity_: Strict-Transport-Security (HSTS) header value, emitted verbatim (and unvalidated) when set to a non-empty string; false (default) or an empty string omits the header. Emission is gated on secure transport — direct TLS or a trusted-proxy-forwarded https/wss protocol — per RFC 6797 §7.2 (HSTS must not be sent over non-secure transport), so it is omitted over plaintext (e.g. loopback development). Recommended production value behind a TLS-terminating reverse proxy or native TLS: "max-age=31536000; includeSubDomains". Caution: includeSubDomains extends the policy to every subdomain of the served host and preload (with submission to hstspreload.org) is effectively irreversible (removal propagates through browser preload lists over ~6–12 months); only use includeSubDomains/preload on a dedicated hostname you fully control, never on a shared host (including localhost) | | performanceStorage | | {
"enabled": true,
"type": "none",
} | {
enabled?: boolean;
type?: string;
uri?: string;
} | Performance storage configuration section:
- _enabled_: enable performance storage
- _type_: 'jsonfile', 'mongodb' or 'none'
- _uri_: storage URI | | stationTemplateUrls | | {}[] | {
file: string;
numberOfStations: number;
provisionedNumberOfStations?: number;
}[] | array of charging station templates URIs configuration section:
- _file_: charging station configuration template file relative path
- _numberOfStations_: template number of stations at startup
- _provisionedNumberOfStations_: template provisioned number of stations after startup

... (README truncated for length)

Chat with me