Skip to content

About

Local KEBA P40 REST integration for Home Assistant: verified monitoring, sessions, energy, discovery and optional controls

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

KEBA KeContact P40 for Home Assistant

A local Home Assistant integration for KEBA KeContact P40 wallboxes, using the charger's HTTPS REST API. No cloud connection or Modbus polling is required.

Validation Release

What you get

  • 33 monitoring entities: charging and connection status, phase currents and voltages, power, lifetime/session energy, session timing and diagnostics.
  • Local discovery, manual setup, automatic JWT renewal and certificate pinning.
  • Charging status kept separate from an open session; exact session energy.
  • Four optional controls, disabled by default; candidate validation is described below.

Tested hardware: one P40 with REST API 2.5.0. P40 Pro and other firmware versions are not yet physically verified. This is an independent community project, not an official KEBA product.

Domain: keba_p40. Version 0.2.5. Requires Home Assistant 2026.9 or newer (Python 3.14).

33 existing monitoring entities retain their unique IDs. This release adds a control-result diagnostic sensor. Four additional controls are registered but disabled by default. Setup, discovery and polling never send controls. No Modbus polling or writes are used.

Stability fixes in 0.2.5

This release includes the production control receipts and passive meter continuity instrumentation, alongside fixes for past validFrom dates, null numberOfPhases, and the Home Assistant NumberEntity.value naming collision. Per-action START/STOP receipts survive subsequent current-limit commands. An ambiguous control is recorded and followed by physical reads; the API never replays an uncertain command. Equal meter readings still publish fresh observation bounds. Wallbox START/STOP/availability commands use separate fresh TLS connections; profile writes and read-only traffic keep the existing shared connection pool.

The reference installation completed overnight charging to its 80% target on 2026-10-18, with 31.1068 kWh delivered, automatic closure and no controller fault. Earlier current-limit and automatic-stop trials exercised the production code. A bounded extra STOP/START sequence in the separate charging controller remains documented; this is not a claim that every vehicle, outage or firmware is validated. The original disconnected-control root cause is not proven.

Regression tests cover Home Assistant entities/registry, supported profile shapes, control receipts, passive meter continuity, current-feedback races and real loopback TLS. Tests use synthetic credentials and never contact a physical charger.

Updating an existing installation

  1. Make a Home Assistant backup. Update while charging and the charging session are both off, with no imminent scheduled charging window.
  2. Download 0.2.5 in HACS, retaining the existing KEBA integration/config entry.
  3. Fully restart Home Assistant; an integration reload alone is insufficient for reliably replacing Python modules already imported by other integrations.
  4. Check that the current limit is numeric, existing entity IDs and enabled controls are retained, and any separate charging controller has no fault. Do not issue a START merely to verify installation.

HACS replaces custom_components/keba_p40. This release includes the stability patches used by the reference installation, so updating that patched 0.2.4 install retains those fixes. Local EV Smart Charging code, helpers, scripts, templates and dashboards are separate; this package neither installs nor updates them. No climate feature is included. Restart discards in-memory receipts/observation history; a separate controller must reconcile physical state and require fresh evidence. For rollback, restore the complete pre-update backup and restart while idle. Public 0.2.4 lacks these fixes and is not an equivalent rollback for a patched install.

Verification status

Monitoring reference: one physical KEBA P40 (device identifiers withheld), package 1.5.1+cert-meter, REST API 2.5.0, BaseIO 5.0.1, meter 3.0.1, safety 3.1.3. Authenticated read-only audit: 2026-10-05. Public fixtures use the audited response structure with synthetic identifiers, energy values, session IDs, dates and durations. The private raw audit is not included. The original 0.2.4 release had no physical control validation. The newer stability observations above describe the controls tested since then.

Field observation: 2026-10-14

Read-only monitoring remained available on the reference P40, with changing phase voltage measurements received in Home Assistant during consecutive observations. The reported package version was still 1.5.1+cert-meter and REST API version 2.5.0. This observation verifies current monitoring connectivity; it does not validate charging controls or the charger's behavior when a vehicle is plugged in.

The owner reported receiving replacement user and installer passwords, a recovery key and a PIN from KEBA. Whether these had been activated on the charger was not verified, and neither replacement login nor recovery was attempted. Continued monitoring does not establish whether existing credentials will remain valid after activation or token renewal. No passwords, recovery keys or PINs are published.

Guest charging without a Home Assistant plan has not been physically verified. This integration does not implement a plan requirement or automatically block charging on plug-in. Such a policy depends on the charger's own authorization/start settings and any separately configured Home Assistant automation. A working monitoring connection alone does not verify that policy.

Relationship to Home Assistant Core

Core PR #173179 proposes a built-in P40 integration. This repository is a separate implementation with its own physical audit and tests; it is not a testing distribution of that PR. Both use the domain keba_p40. Do not install both implementations together. A future transition will require checking config-entry and entity compatibility.

Install from ZIP

  1. Back up Home Assistant and any existing custom_components/keba_p40 directory.
  2. Extract the ZIP. Copy its custom_components/keba_p40 directory into /config/custom_components/keba_p40. Keep the folder name keba_p40.
  3. Restart Home Assistant. Open Settings → Devices & services → Add integration → KEBA KeContact P40, or accept its discovery card.
  4. Enter p40.local or 192.0.2.14, HTTPS port 8443, normal KEBA username and password. These are stored as standard HA config-entry credentials. JWTs stay in memory. HA config backups contain credentials; protect those backups.
  5. Use the device certificate SHA-256 fingerprint with CA validation disabled for a pinned self-signed certificate, or trust its certificate in HA. Disabling CA validation without a fingerprint provides encryption without server identity verification. No certificate is guessed or bundled into this package.
  6. Confirm the model, serial, energy, state, phase measurements and versions before enabling any controls. All 33 monitoring entities are enabled by default.
  7. To test a control, open its entity settings and enable that specific entity. Follow PHYSICAL_TEST_PLAN.md. No controls are automatically called on enable.

Both HA and the charger must be able to reach each other on the local network. Port 502 is irrelevant to this integration. p40.local requires working mDNS.

HACS

Add https://github.com/Rschmidt79/home-assistant-keba-p40 in HACS → Custom repositories → Integration. Download the latest release, then restart Home Assistant. The existing config entry and current entities are reused. Do not delete the integration or create a duplicate entry.

Remove the old Ich-h4lt repository from HACS management first so it cannot overwrite this integration. Keep the HA config entry/device. Back up your HA configuration before switching repositories. Future releases appear as HACS updates. This is a custom repository, not an entry in the default HACS catalog.

Entities and semantics

See ENTITIES.md for all 37 entities and CONTROLS.md for request contracts. sessionActive means an open session, not charging. Charging is state=CHARGING. The observed reference had an open BLOCKED session, READY_FOR_CHARGING and 0 W. Actual currents and offered PWM current are separate. Total energy is a lifetime total_increasing kWh sensor suitable for the Energy Dashboard. Session energy uses exact energyConsumed, has state_class=total and last_reset=session_start; it is never total_increasing across sessions. energyConsumedInKwh is not used. Times and duration use milliseconds; session duration includes waiting. Missing data and API failures produce unavailable entities, never synthetic zero. Serial is stable identity; alias is metadata. No vehicle identity inference exists.

RFID / session token ID

The Session token ID sensor exposes tokenId from the selected session. The KEBA REST schema defines this as the Token.id that authorized that session. It is an opaque identifier: case and leading zeros are preserved. No separate token list request, authorization change or charging command is made.

Attributes include session_id, session_start, session_end, session_status and active_session. After closure the latest session's ID can remain visible with active_session: false; it is historical, not a fresh chip swipe. Missing or invalid IDs become unavailable and never inherit the previous session's chip. The sensor follows existing session polling (20 seconds or plug/session changes), so it is not an instantaneous reader event and does not report every swipe.

Automations may map an assigned chip to an explicit vehicle selection, but the chip identifies the assigned tag, not the connected vehicle or its battery SOC. Use a fresh active session and its session identity when binding a selection; never use a historical tag as proof for a new connection. This integration does not add vehicle mappings, bypass charging plans, or synthesize battery data.

Chip IDs are available locally in HA states/history but redacted from integration diagnostics. Do not publish real IDs in issues or test fixtures. Session chip values are schema-supported; representation on each firmware requires live verification.

Polling and authentication

Wallbox: 5 s; sessions: 20 s or session/plug transition; Modbus/load-management config and editable baseline profile: 120 s; device/version/alias: 6 h. The Modbus configs are read via REST, not Modbus. Authentication and reads are serialized by an async lock. Expired access tokens refresh with POST /v2/jwt/refresh; rejected refreshes fall back to login. Controls obtain a fresh login token under the same lock, so non-fresh-token restrictions are respected. No uncertain write is replayed. No username, password, JWT, Authorization header or raw API response is logged or returned by diagnostics. Diagnostic output also redacts identifying information.

Limitations

Current control edits only a simple all-day ChargePointMaxProfile at stack level zero, with exactly one wallbox. It preserves the existing item except its current, refuses validity windows, complex schedules and explicit phase settings, and does not create OCPP-sourced profiles or change OCPP configuration. Other higher priority profiles may further restrict effective PWM; a cap is not a promise of actual current. A missing/complex profile leaves the number unavailable; monitoring continues.

Pause/resume is intentionally not exposed. REST 2.5.0 has no documented dedicated pause/resume endpoint. Zero-current profile suspension and same-session resumption are not established by our REST audit/specification. Stop/start and out-of-order availability must not silently substitute for session-preserving pause/resume. This requested capability remains pending authoritative semantics and physical validation. No phase-switching control is implemented.

Upgrade from 0.1.0

Replace the integration directory, restart HA and retain the existing config entry. No migration or unique-ID change is needed: existing IDs remain {serial}_{key}. The display name drops “Read Only”. The four new controls start disabled. Do not install this alongside Ich-h4lt's integration: both use domain keba_p40 and cannot coexist under that domain. Entity IDs may retain their prior names after upgrades.

Troubleshooting

  • Connection failure: check IP/hostname, LAN/VLAN routing, port 8443 and certificate.
  • Authentication: reauthenticate with KEBA credentials; never paste JWTs into logs.
  • Number unavailable: inspect the baseline profile with authorized GET; complex or phase-specific profiles are intentionally protected. HTTP 404 means unsupported.
  • Control error: read physical state before trying again. A timeout can occur after the charger accepted a command. The integration does not retry the write.
  • Availability enabled but no charging: vehicle, authorization and charging profiles still determine whether charging actually starts.
  • Use HA Reload for retry. Unload clears credentials/tokens from the API instance and removes coordinator listeners; the shared HA HTTP session remains owned by HA.

Development

Install requirements_test.txt into a Python 3.14 environment. Run pytest --cov=custom_components.keba_p40, ruff check . and ruff format --check .. pytest disables network sockets by default. See VALIDATION.md for actual results, and PHYSICAL_TEST_PLAN.md for the pending real-device control tests. No automatic pricing, PV/load balancing, phase switching, firmware, reboot, unlock, OCPP changes or Modbus writes are implemented.

0.2.1 compatibility fix

Old Ich-h4lt config entries omitted username because they always used admin. Version 0.2.1 migrates those entries locally, fills the documented old admin username, preserves credentials/serial, and consolidates old options into data. It does not delete the entry or change its identity. Replace the folder and restart HA; the existing entry is reused. Missing passwords trigger reauthentication rather than a KeyError. No physical control request is part of migration.

0.2.2: legacy registry cleanup

After successful setup and registration of all 33 monitoring entities, this release removes only the 25 known legacy entities from the old implementation, matched by exact old unique ID, platform, entity domain and config entry. Current unique IDs/HA entity IDs remain unchanged. Other devices, config entries and unknown prefixed entities are untouched. Cleanup is idempotent.

Before upgrading, update any dashboards/automations using the old entities and make a Home Assistant backup. No automatic reference remapping is attempted. The cleanup uses HA's entity registry API, not direct .storage editing. The missing DOMAIN import reported in the locally installed cleanup is fixed and protected by registry/setup tests and ruff F821 checks.

Publishing updates

Change the manifest version, run tests/ruff/hassfest, commit and push to main, then create a matching GitHub release such as v0.2.5. HACS downloads the release source tree. A tag alone is not a release. Active GitHub Actions in .github/workflows/checks.yaml run pytest, ruff, hassfest and HACS validation. Tests block network sockets and no CI job contacts a real charger.

About

Local KEBA P40 REST integration for Home Assistant: verified monitoring, sessions, energy, discovery and optional controls

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages