Sign inSign up

wocha/ocpp-cp-admin

By wocha

β€’Updated 4 days ago

OCPP 1.6 Charge Point Management System (CSMS) for operating and monitoring EV charging infrastructu

Image
0

10K+

wocha/ocpp-cp-admin repository overview

⁠OCPP CP Admin

Charge Point Management System (CSMS) for Charge Point Operators (CPO), based on the OCPP 1.6 protocol.

OCPP CP Admin enables monitoring and managing electric vehicle charging infrastructure: charge point management, user management, charge transactions, real-time alerts, and an analytics dashboard.

πŸ‡«πŸ‡· Version franΓ§aise⁠


⁠Table of Contents


⁠Features

⁠Charge Point Management
  • Manual registration or automatic discovery of charge points
  • Approval of pending charge points
  • Assignment of charge points to sites
  • Real-time monitoring (connector status, heartbeat, errors)
  • Remote charge point configuration (GetConfiguration / ChangeConfiguration)
  • OCPP message history (CALL / CALLRESULT / CALLERROR)
⁠Site and User Management
  • Multi-site architecture
  • Hierarchical roles: Admin, Manager, User
  • Per-site and per-user authorization
  • Local authentication (email / password) or Google OAuth 2.0
  • Password reset via email with secure token
⁠Transactions and Charge Monitoring
  • Active and completed transaction tracking
  • Real-time data: energy (Wh), power (W), current (A per phase), state of charge (SOC %), temperature (Β°C), voltage (V per phase), frequency (Hz)
  • Transaction history with filters
  • CSV export of transactions
  • Personal dashboard for users
⁠Error Event History
  • Persistent log of hardware/network errors: StatusNotification faults, disconnections (after grace period), heartbeat timeouts
  • Global view filterable by charge point, event type, OCPP version, and date range
  • Accessible to managers and admins
  • Real-time updates via WebSocket
⁠RFID Badge Management
  • Badge creation and management (ID Tags)
  • Automatic web tag generation for remote starts
  • Expiration and authorization rejection tracking
⁠Charging Profiles
  • Create and apply charging profiles on charge points via SetChargingProfile
  • Supported purposes: ChargePointMaxProfile (global station power cap) and TxDefaultProfile (default transaction profile)
  • Periodic (weekly) or relative scheduling with configurable power per time slot
  • Targeted or full profile clearing via ClearChargingProfile
  • Automatic re-application of managed profiles on charge point reconnection
⁠Connector Reservations
  • Reserve a connector for a given RFID badge via OCPP 1.6 ReserveNow
  • On-demand cancellation via CancelReservation
  • Automatic expiration detection from StatusNotification
⁠Multi-Channel Notifications
  • Email (SMTP via Nodemailer)
  • Web Push (browser notifications via Service Worker)
  • Pushover (mobile push notifications)
  • 22 event types with role-based filtering
  • Per-user and per-channel preferences
⁠Dashboard and Analytics
  • Real-time statistics: connected charge points, active transactions, connector states
  • Charging KPIs: energy, duration, frequency
  • Historical charts (configurable date range)
⁠Security and Monitoring
  • Connection loop detection (flapping)
  • Duplicate identity detection (same identifier from multiple IPs)
  • Rate limiting on APIs and authentication
  • HTTP security headers (Helmet)
  • Structured logging with file rotation
⁠Progressive Web Application (PWA)
  • Installable on desktop and mobile (Web App Manifest)
  • Responsive interface (mobile-first)
  • Light/dark theme
  • Push notifications via Service Worker
  • /healthz endpoint for monitoring
  • /metrics endpoint in Prometheus text format (optional bearer token protection)

⁠Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Browser / Mobile                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ HTTP/HTTPS
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Express Web Server (Port 3000/3001)             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ REST API                                           β”‚ β”‚
β”‚  β”‚ Auth, Sites, Users, Charge Points, Transactions    β”‚ β”‚
β”‚  β”‚ Notifications, Dashboard                           β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚              β”‚              β”‚
β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
β”‚ SQLite  β”‚  β”‚ Sessions β”‚  β”‚ Real-time   β”‚
β”‚  (DB)   β”‚  β”‚ (SQLite) β”‚  β”‚ broadcast   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         OCPP Server (WS Port 9000 / WSS Port 9001)     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ OCPP 1.6 RPC                                       β”‚ β”‚
β”‚  β”‚ Authentication (password + client certificate)     β”‚ β”‚
β”‚  β”‚ Handlers: Boot, Authorize, Transactions ...        β”‚ β”‚
β”‚  β”‚ Remote commands: RemoteStart, ChangeConfig         β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ WebSocket OCPP 1.6
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚   EVSE Stations β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
⁠Tech Stack
ComponentTechnology
RuntimeNode.js 22
Web frameworkExpress 5
DatabaseSQLite 3 (better-sqlite3, WAL mode)
OCPP protocolocpp-rpc (OCPP 1.6-J, OCPP 2.0.1 ready)
AuthenticationPassport.js (local + Google OAuth 2.0)
Password hashingbcryptjs
HTTP securityHelmet, express-rate-limit
EmailNodemailer
Web Pushweb-push
LoggingWinston + daily rotation
i18ni18next
LintingESLint + Prettier

⁠Prerequisites

  • Node.js >= 22
  • npm >= 10
  • Or Docker / Docker Compose

⁠Installation

⁠Node.js Installation
# Clone the repository
git clone <repository-url>
cd ocpp-cp-admin

# Install dependencies
npm install

# Copy the sample configuration
cp config/config.sample.json config/config.json

Edit config/config.json according to your needs (see the Configuration⁠ section).

⁠Docker Installation

The image is available on GitHub Container Registry and Docker Hub:

docker pull ghcr.io/wocha-fr/ocpp-cp-admin:latest
# or
docker pull wocha/ocpp-cp-admin:latest

Or build the image locally:

docker build -t ghcr.io/wocha-fr/ocpp-cp-admin .

Four Docker Compose files are available in the docker/ folder, suited for different deployment scenarios:

FileDescription
docker-compose.http.ymlApp only β€” HTTP + WS (ports 3000/9000)
docker-compose.https.ymlApp only β€” HTTPS + WSS (ports 3001/9000/9001, certbot included)
docker-compose.ymlFull stack: Traefik (HTTPS, TLS termination) + App + FTP
docker-compose.tls.ymlFull stack: Traefik (HTTPS + WSS passthrough) + cert export + App + FTP
# Example: full stack with Traefik
docker compose -f docker/docker-compose.yml up -d

# Example: app only HTTP
docker compose -f docker/docker-compose.http.yml up -d

Traefik-based stacks include:

  • Reverse proxy with host-based routing (cpadmin.local, ws.cpadmin.local)
  • FTP server for charge point diagnostics retrieval
  • Let's Encrypt support (TLS variant)
  • TCP passthrough for OCPP WSS with client certificate authentication (TLS variant)

See docker/README.md⁠ for details on each compose file.

⁠Bare-metal Deployment (systemd)

For servers running without Docker, a ready-to-use systemd unit is provided in scripts/.

1. Create a dedicated user and deploy the application:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin ocpp-cp-admin
sudo mkdir -p /opt/ocpp-cp-admin
sudo cp -r . /opt/ocpp-cp-admin
sudo chown -R ocpp-cp-admin:ocpp-cp-admin /opt/ocpp-cp-admin
cd /opt/ocpp-cp-admin && sudo -u ocpp-cp-admin npm ci --omit=dev

2. Configure environment variables:

# Copy the template and fill in your values
sudo mkdir -p /etc/ocpp-cp-admin
sudo cp scripts/env.example /etc/ocpp-cp-admin/env
sudo nano /etc/ocpp-cp-admin/env
sudo chmod 600 /etc/ocpp-cp-admin/env

# Then uncomment the EnvironmentFile= line in the unit file:
# EnvironmentFile=/etc/ocpp-cp-admin/env

See scripts/env.example⁠ for all available variables.

3. Install and start the service:

sudo cp scripts/ocpp-cp-admin.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now ocpp-cp-admin

# View logs
journalctl -u ocpp-cp-admin -f

Exposed Ports:

PortUsage
3000Web Interface (HTTP)
3001Web Interface (HTTPS, if enabled)
9000OCPP Server (WebSocket)
9001OCPP Server (WebSocket Secure, if enabled)

Volumes:

VolumeContents
/app/configConfiguration, database, and certificates (certs/)
/app/logsLog files
/app/public/imgStatic images
/app/locales-customCustom locale files (add or override translations)
The /healthz endpoint is used for Docker health checks (HTTP GET, every 30s).

The /metrics endpoint exposes Prometheus-format metrics (chargepoints, transactions, connectors by status, uptime, heap). It is accessible without authentication by default; set metrics.bearerToken (or CPADMIN_METRICS_TOKEN) to require a bearer token.

On first startup, if config/config.json does not exist, it is automatically created from config.sample.json.

The entrypoint runs as root to seed default files and fix volume permissions, then drops privileges to a dedicated non-root user (app) via su-exec.


⁠Environment Variables

Values from config.json can be overridden by environment variables. The JSON file remains the base configuration; environment variables take precedence when set.

⁠Deployment / URLs
VariableJSON ConfigExample
CPADMIN_PUBLIC_URLwebui.publicUrlhttps://cpadmin.example.com
CPADMIN_HTTP_HOSTwebui.httpHost0.0.0.0
CPADMIN_TRUST_PROXYwebui.trustProxytrue (required behind a reverse proxy)
CPADMIN_OCPP_WS_URLocpp.ocppWsUrlws://ws.example.com
CPADMIN_OCPP_WSS_URLocpp.wss.ocppWsUrlwss://ws.example.com:9001
CPADMIN_DIAGNOSTICS_URLocpp.diagnosticsLocationftp://ftp.example.com
CPADMIN_SESSION_SECRETwebui.sessionSecret
⁠General Configuration
VariableJSON ConfigExample
CPADMIN_LOGLEVELlogleveldebug, info, error
LOG_CONSOLE(no JSON equivalent)true β€” force console log output (useful for temporary debugging in production)
CPADMIN_LANGUAGElanguageAny locale code from locales/ folder (e.g. fr, en)
CPADMIN_CPO_NAMEcpoNameMy CPO
⁠Feature Activation
VariableJSON ConfigExample
CPADMIN_WEBUI_HTTPS_ENABLEDwebui.https.enabledtrue (enable native HTTPS on the web interface)
CPADMIN_OCPP_WSS_ENABLEDocpp.wss.enabledtrue (enable native WSS on the OCPP server)
⁠OCPP Behavior
VariableJSON ConfigExample
CPADMIN_OCPP_STRICT_MODEocpp.strictModefalse (disable strict OCPP 1.6 validation)
CPADMIN_OCPP_CALL_TIMEOUTocpp.callTimeoutSeconds45
CPADMIN_OCPP_AUTO_ADDocpp.autoAddUnknownChargepointstrue (auto-register unknown charge points)
CPADMIN_OCPP_PENDING_UNKNOWNocpp.pendingUnknownChargepointstrue (queue unknown charge points for approval)
CPADMIN_OCPP_V16_ENABLEDocpp.v16.enabledfalse (disable OCPP 1.6 support)
CPADMIN_OCPP_V201_ENABLEDocpp.v201.enabledtrue (enable OCPP 2.0.1 support β€” in development)
⁠Mail Configuration
VariableJSON ConfigExample
CPADMIN_MAIL_ENABLEDnotifs.mail.enabledtrue
CPADMIN_MAIL_FROMnotifs.mail.fromCPADMIN <[email protected]>
CPADMIN_MAIL_HOSTnotifs.mail.transport.host
CPADMIN_MAIL_PORTnotifs.mail.transport.port
CPADMIN_MAIL_USERnotifs.mail.transport.auth.user
CPADMIN_MAIL_PASSnotifs.mail.transport.auth.pass
CPADMIN_MAIL_SECUREnotifs.mail.transport.securetrue (SSL/TLS from start)
⁠WebPush Configuration
VariableJSON ConfigExample
CPADMIN_WEBPUSH_ENABLEDnotifs.webpush.enabledtrue
CPADMIN_VAPID_PUBLIC_KEYnotifs.webpush.vapidPublicKey
CPADMIN_VAPID_PRIVATE_KEYnotifs.webpush.vapidPrivateKey
CPADMIN_VAPID_SUBJECTnotifs.webpush.vapidSubjectmailto:[email protected]
⁠Pushover Configuration
VariableJSON ConfigExample
CPADMIN_PUSHOVER_ENABLEDnotifs.pushover.enabledtrue
⁠Notification Defaults
VariableJSON ConfigExample
CPADMIN_NOTIF_DISABLED_EVENTSnotifs.defaultDisabledEventsconnector_available,connector_unavailable
⁠Google Auth Configuration
VariableJSON ConfigExample
CPADMIN_GOOGLE_AUTH_ENABLEDauth.google.enabledtrue
CPADMIN_GOOGLE_CLIENT_IDauth.google.client_id
CPADMIN_GOOGLE_CLIENT_SECRETauth.google.client_secret
⁠Prometheus Metrics
VariableJSON ConfigExample
CPADMIN_METRICS_TOKENmetrics.bearerTokenmy-secret-token

If not set, /metrics is accessible without authentication (suitable for private/Docker networks).

Booleans (true/false) and numbers are automatically converted. Secrets are always treated as strings.


⁠Configuration

The configuration file is config/config.json. In development mode (NODE_ENV=development), config/config.dev.json is used if it exists.

Configuration values can be overridden by environment variables (see the Environment Variables⁠ section).

⁠Configuration Editor (UI)

Administrators can edit the configuration directly from the web interface via Settings β†’ Configuration. The editor displays all parameters organized by section in a table with three columns:

  • File value β€” the value currently stored in config.json
  • Env. variable β€” the associated environment variable name and its current value (or not set if undefined)
  • New value β€” editable field pre-filled with the effective value (env override takes precedence over the file value)

Required fields are validated before saving. The application restarts automatically after a successful save.

Environment variables are informational only β€” they cannot be modified from the UI. The editor writes only to config.json.

⁠General
ParameterTypeDefaultDescription
loglevelstring"error"Log level: error, warn, info, debug
languagestring"fr"Default application language (any locale code from locales/ folder, e.g. fr, en)
dbnamestring"cpadmin.db"SQLite database file name
cpoNamestring"CP Admin"Organization name (displayed in the interface)
⁠Web Interface (WebUI)
"webui": {
  "httpHost": "localhost",
  "httpPort": 3000,
  "trustProxy": false,
  "publicUrl": "http://localhost:3000",
  "sessionSecret": "",
  "https": {
    "enabled": false,
    "httpsPort": 3001,
    "certFile": "certs/server.crt",
    "keyFile": "certs/server.key"
  }
}
ParameterDescription
httpHostHTTP listen address (0.0.0.0 to listen on all interfaces)
httpPortHTTP port
trustProxyEnable if behind a reverse proxy (true or number of proxies)
publicUrlPublic URL of the application (used in emails, Google OAuth callback)
sessionSecretSecret key for sessions (auto-generated if empty on each startup)
https.enabledEnable HTTPS server
https.httpsPortHTTPS port
https.certFile / keyFilePaths to TLS certificate and key files (relative to the config/ folder)
⁠OCPP Server
"ocpp": {
  "host": "0.0.0.0",
  "wsPort": 9000,
  "strictMode": true,
  "callTimeoutSeconds": 45,
  "autoAddUnknownChargepoints": false,
  "pendingUnknownChargepoints": true,
  "ocppWsUrl": "ws://ws.cpadmin.local:9000",
  "diagnosticsLocation": "ftp://example.com/diagnostics",
  "v16":  { "enabled": true },
  "v201": { "enabled": false },
  "wss": {
    "enabled": false,
    "wssPort": 9001,
    "strictClientCert": false,
    "ocppWsUrl": "wss://ws.cpadmin.local:9001",
    "rsa": { "certFile": "...", "keyFile": "..." },
    "ecdsa": { "certFile": "...", "keyFile": "..." },
    "caFile": ""
  }
}
ParameterDescription
hostOCPP server listen address
wsPortWebSocket (WS) port
strictModeOCPP strict mode (message validation)
callTimeoutSecondsTimeout in seconds waiting for a response to an OCPP call
autoAddUnknownChargepointsAutomatically add unknown charge points that connect
pendingUnknownChargepointsPut unknown charge points pending admin approval
ocppWsUrlOCPP WebSocket URL to communicate (for charge point configuration)
diagnosticsLocationDestination URL for diagnostics upload
v16.enabledEnable OCPP 1.6 support (default: true) β€” set to false to disable; a warning is logged and all connections are rejected if both versions are disabled
v201.enabledEnable OCPP 2.0.1 support (default: false) β€” in development, not yet fully functional
wss.enabledEnable WebSocket Secure (TLS)
wss.strictClientCertRequire a valid client certificate
wss.rsa / ecdsaServer certificates for WSS (dual algorithm supported, paths relative to config/ folder)
wss.caFileCertificate authority for client certificate validation (path relative to config/ folder)
⁠Notifications
"notifs": {
  "authRejectThreshold": 3,
  "authRejectWindowMinutes": 5,
  "flapThreshold": 4,
  "flapWindowMinutes": 2,
  "refusedCooldownMinutes": 60,
  "reconnectGracePeriodSeconds": 60,
  "availabilityDebounceSeconds": 5,
  "mail": {
    "enabled": false,
    "from": "CPADMIN <[email protected]>",
    "transport": {
      "host": "smtp.example.com",
      "port": 587,
      "secure": false,
      "auth": { "user": "...", "pass": "..." }
    }
  },
  "webpush": {
    "enabled": false,
    "vapidSubject": "mailto:[email protected]",
    "vapidPublicKey": "",
    "vapidPrivateKey": ""
  },
  "pushover": {
    "enabled": false
  }
}
ParameterDescription
authRejectThresholdNumber of RFID authorization rejections before notification
authRejectWindowMinutesTime window for RFID rejection counting (minutes)
flapThresholdNumber of rapid reconnections before flapping alert
flapWindowMinutesTime window for flapping detection (minutes)
refusedCooldownMinutesCooldown between two chargepoint_refused notifications for the same identity (default: 60 min)
reconnectGracePeriodSecondsGrace period in seconds before sending the offline notification. If the chargepoint reconnects within this delay, both offline and online notifications are suppressed (default: 60)
availabilityDebounceSecondsDebounce delay (seconds) before sending Available/Unavailable notifications. Prevents spurious alerts from chargepoints that rapidly toggle status on connection (default: 5)
mail.enabledEnable email notifications
mail.fromSender address
mail.transportSMTP transport configuration (Nodemailer)
webpush.enabledEnable Web Push notifications
webpush.vapid*VAPID keys for Web Push (to be generated)
`pushover.enable

Tag summary

Content type

Image

Digest

sha256:adc7da9d5…

Size

73.2 MB

Last updated

3 months ago

docker pull wocha/ocpp-cp-admin