2026-08-18 23:15:12 +02:00
# easy-occp
2026-08-18 23:41:22 +02:00
🌐 [English ](README.md ) · [Deutsch ](README.de.md ) · [Français ](README.fr.md ) · [Español ](README.es.md )
2026-08-18 23:15:12 +02:00
[](https://github.com/hilman2/easy-occp/actions/workflows/ci.yml)
[](https://github.com/hilman2/easy-occp/releases/latest)
[](LICENSE)
2026-08-18 23:41:22 +02:00
Simple management tool for EV charging stations (wallboxes), built for **SMBs with 1– 10 wallboxes** .
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
- **One binary, one SQLite file** – no external database, no message broker.
- **OCPP 1.6J** (complete) + **OCPP 2.0.1** (WebSocket scaffold, BootNotification / TransactionEvent) + **OCPP 1.5 SOAP** (scaffold for Boot/Heartbeat).
- **Modern web UI** (Askama + htmx), local users with Argon2 passwords.
- Active Directory (LDAP) and Microsoft Entra (OIDC) are prepared as configuration fields – the concrete bind/flow implementations will follow.
- Runs on **Windows** (primary focus) **and Linux** .
2026-08-18 23:15:12 +02:00
## Features
2026-08-18 23:41:22 +02:00
| Area | Status |
2026-08-18 23:15:12 +02:00
|-----------------|--------|
2026-08-18 23:41:22 +02:00
| Wallbox inventory + status (online/offline, connectors, firmware) | ✅ |
| RFID chip management, enrollment via "learning window" (2 min, Authorize intercept) | ✅ |
| Chip → employee assignment, guest chips, validity expiry | ✅ |
| Remote unlocking for guests, billing to guest label | ✅ |
| Live values during charging (charged kWh, current power, SoC) | ✅ |
| Transaction list, filter by user | ✅ |
| Statistics by month / quarter / year | ✅ |
| User management (admin/user), local password | ✅ |
| Multilingual UI (Deutsch, English, Français, Español) | ✅ |
| Active Directory (LDAP) | 🟡 Config prepared |
| Entra ID (OIDC) | 🟡 Config prepared |
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
## Getting started
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
**Prebuilt binaries** (Windows x64, Linux x64) are available under
[Releases ](https://github.com/hilman2/easy-occp/releases/latest ) — unpack,
run `easy-occp.exe` or `easy-occp` , done (see `INSTALL.md` in the package).
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
Or build it yourself:
2026-08-18 23:15:12 +02:00
```bash
2026-08-18 23:41:22 +02:00
# once: create a config (optional)
2026-08-18 23:15:12 +02:00
copy config.example.toml config.toml
2026-08-18 23:41:22 +02:00
# Build + start
2026-08-18 23:15:12 +02:00
cargo run --release
```
2026-08-18 23:41:22 +02:00
Then open the UI at <http://localhost:8080>. **Default login on first start:** `admin` / `admin` – please change the password right away under "Users".
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
Forgot the admin password?
2026-08-18 23:15:12 +02:00
```bash
2026-08-18 23:41:22 +02:00
cargo run --release -- --reset-admin "newPassword123"
2026-08-18 23:15:12 +02:00
```
2026-08-18 23:41:22 +02:00
## Configuring a wallbox
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
Wallboxes establish a WebSocket connection:
2026-08-18 23:15:12 +02:00
```
ws://<host>:8080/ocpp/<ChargePointId>
```
2026-08-18 23:41:22 +02:00
Subprotocols are negotiated automatically (`ocpp1.6` or `ocpp2.0.1` ).
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
For older OCPP 1.5 devices (SOAP):
2026-08-18 23:15:12 +02:00
```
POST http://<host>:8080/ocpp15
```
2026-08-18 23:41:22 +02:00
### Live meter readings during charging
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
When an OCPP 1.6 wallbox connects, the server automatically configures it to
report the meter reading, power, and (if available) SoC every 30 seconds during
a charging session (`MeterValueSampleInterval` , `MeterValuesSampledData` ).
The interval can be adjusted via `config.toml` ; `0` disables the
auto-configuration:
2026-08-18 23:15:12 +02:00
```toml
[ ocpp ]
meter_interval_s = 30
```
2026-08-18 23:41:22 +02:00
The cockpit and the wallbox detail page automatically refresh active charging
sessions every 10 seconds (htmx polling). If a wallbox does not report power,
it is derived from the last two meter readings.
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
## Data storage
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
Everything lives in **one SQLite file** at `data/easy-occp.db` (changeable via `config.toml` ). Migrations reside in `migrations/` and are applied automatically at startup.
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
### Sanity checks on incoming data
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
- **Timestamps**: >24 h in the future or >10 years in the past are discarded – fallback to the server clock.
- **StartTransaction / StopTransaction**: Idempotent against repeats; decreasing meter values are corrected.
- **StatusNotification**: UPSERT per (wallbox, connector) – no duplicates.
- **MeterValues**: negative values are discarded, SoC validated to 0– 100 %, kWh → Wh normalized.
- **Enrollment**: A newly captured tag is assigned to exactly one open learning-window session.
2026-08-18 23:15:12 +02:00
2026-08-18 23:41:22 +02:00
## Project layout
2026-08-18 23:15:12 +02:00
```
src/
2026-08-18 23:41:22 +02:00
main.rs – entry point, Tokio runtime, SQLite pool
config.rs – TOML configuration
db.rs – bootstrap + helpers (Argon2, settings)
2026-08-18 23:15:12 +02:00
error.rs – AppError / IntoResponse
2026-08-18 23:41:22 +02:00
auth/ – session cookies + local login
domain/ – data models (FromRow)
2026-08-18 23:15:12 +02:00
ocpp/
2026-08-18 23:41:22 +02:00
wire.rs – OCPP JSON frame parser
hub.rs – registry of all active connections
ocpp16.rs – OCPP 1.6J (complete)
ocpp20.rs – OCPP 2.0.1 (bootstrap)
soap15.rs – OCPP 1.5 SOAP endpoint
web/ – axum router, Askama views
templates/ – HTML templates (Askama)
static/ – CSS + htmx shim (embedded via rust-embed)
migrations/ – SQLite migrations
2026-08-18 23:15:12 +02:00
```
2026-08-18 23:41:22 +02:00
## License
2026-08-18 23:15:12 +02:00
MIT