v0.2.2 — BMS pause/resume promotion
What's new
Bug fixes (since v0.2.1)
-
Significant energy loss after a brief pause in charging (#23) — the balancing-cycle gate introduced in v0.2.1 was correct in suppressing real BMS battery balancing, but it also blocked legitimate sustained charging when the car briefly paused for non-balancing reasons (BMS top-up after primary charge, schedule boundaries, brief door-lock interrupts, etc.). Live observation on 2026-04-26 with a Peugeot 3008 PHEV showed 3.94 kWh — about 30 % of a single plug-in event's energy — was unrecorded over 75 minutes after a 29-second BMS pause.
Fix: when the gate is engaged but objective evidence shows charging is sustained, promotion fires and starts a new tracked session. Two thresholds combined with logical OR:
- H1 (duration): current uninterrupted Charging interval ≥ 5 minutes. Real balancing pulses observed in production max out at 119 seconds, so this threshold catches sustained resumption while never firing on early balancing.
- H2 (energy): cumulative
whdelta since gate engagement ≥ 0.5 kWh. Real balancing pulses deliver 0.05–0.12 kWh each, so this provides ~4× safety margin against false positives.
The new session's energy baseline equals the charger's current
whreading at promotion time, so future delta is captured cleanly with no double-counting.True BMS balancing (multiple short pulses with low energy) continues to be suppressed exactly as in v0.2.1. The settling pulse at the end of a balancing sequence (~25 minutes sustained) will trigger H1 and produce a separate session record — this is desired behaviour because the settling pulse delivers real energy that should be recorded.
Defensive paths
- Promotion only evaluates when
car_status == "Charging". - H2 short-circuits cleanly when the energy entity is unavailable; H1 continues to work independently.
- H1 baseline is only updated on real state transitions, so duplicate
Chargingevents from attribute-only updates cannot reset the timer.
Observability
- New debug-log categories:
GATE_ENGAGED(when the gate engages with the energy baseline),GATE_PROMOTE(with trigger reason, measured duration, and energy delta),GATE_CLEAR(with suppressed-event count summary). - The existing
BALANCING_SKIPdebug-log message wording is preserved verbatim and emission is now coalesced — one entry per gate-engaged window with the count preserved in memory and surfaced onGATE_PROMOTE/GATE_CLEAR. No more 8 000+ entries flooding the debug log during long stuck windows.
Internals
- 15 new tests covering the promotion paths, balancing-still-suppressed regression, settling-pulse promotion, gate-clear semantics, recovery integration, log contracts, and a regression guard for duplicate state-change events. 1 PR-18 test updated to match the new BALANCING_SKIP coalescing semantics.
- Threshold defaults exposed as
DEFAULT_PROMOTE_DURATION_S = 300andDEFAULT_PROMOTE_ENERGY_KWH = 0.5inconst.py— ready for future options-flow exposure if fleet observation justifies user tuning.
Upgrade
Via HACS: open Home Assistant → HACS → EV Charging Manager → Update. Restart Home Assistant after the update completes.