Skip to content

v0.2.2 — BMS pause/resume promotion

Choose a tag to compare

@cryptotomte cryptotomte released this 28 Apr 10:48
dd8c3ad

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 wh delta 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 wh reading 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 Charging events 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_SKIP debug-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 on GATE_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 = 300 and DEFAULT_PROMOTE_ENERGY_KWH = 0.5 in const.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.