Skip to content

Protect PHEV charging session from sync-down corruption#243

Merged
kvanbiesen merged 1 commit intokvanbiesen:mainfrom
renaudallard:main
Feb 14, 2026
Merged

Protect PHEV charging session from sync-down corruption#243
kvanbiesen merged 1 commit intokvanbiesen:mainfrom
renaudallard:main

Conversation

@renaudallard
Copy link
Copy Markdown
Contributor

During PHEV AC charging, stale batteryManagement.header values could trigger the sync-down path in update_bmw_soc(), resetting anchor_soc and total_energy_kwh to zero. This caused two production issues:

  1. SOC flicker: stale header (e.g. 5%) in same message as fresh charging.level (45%) briefly drops prediction before sync-up recovers — session data was destroyed in the interim.

  2. Session discarded: at charge end, header arrives before status=NOCHARGING. Sync-down resets anchor to header value and energy to 0. Pending session then has soc_gain=0 and is discarded, losing the full charging session for learning.

Fix: when is_charging is True, the PHEV sync-down now only updates display values (_last_predicted_soc, session.last_predicted_soc) but preserves session.anchor_soc, total_energy_kwh, and last_energy_update. When not charging, full reset is preserved (no change).

Verified paths:

  • BEV unaffected: entire block gated by _is_phev (BEVs take the elif-is_charging path which already has sync-up-only protection)
  • Bug 1 trace: header=5 sets display to 5, session data preserved; charging.level=45 then syncs up cleanly. Entity never sees flicker (same async context, debounce fires after both processed)
  • Bug 2 trace: header=56 with predicted=58 syncs display down but keeps anchor_soc=3 and total_energy_kwh=8.5; end_session reads soc_gain=56-3=53% with real energy — session preserved for learning
  • Monotonicity guard: after sync-down sets session.last_predicted_soc low, next get_predicted_soc computes anchor+energy and max() picks the real prediction — display self-corrects on next tick
  • Not-charging: full reset unchanged (anchor + energy zeroed)
  • PHEV detection: i4 eDrive40 (BEV) safe — _is_metadata_bev override prevents misclassification even with erroneous fuel descriptors

During PHEV AC charging, stale batteryManagement.header values could
trigger the sync-down path in update_bmw_soc(), resetting anchor_soc
and total_energy_kwh to zero. This caused two production issues:

1. SOC flicker: stale header (e.g. 5%) in same message as fresh
   charging.level (45%) briefly drops prediction before sync-up
   recovers — session data was destroyed in the interim.

2. Session discarded: at charge end, header arrives before
   status=NOCHARGING. Sync-down resets anchor to header value and
   energy to 0. Pending session then has soc_gain=0 and is discarded,
   losing the full charging session for learning.

Fix: when is_charging is True, the PHEV sync-down now only updates
display values (_last_predicted_soc, session.last_predicted_soc) but
preserves session.anchor_soc, total_energy_kwh, and last_energy_update.
When not charging, full reset is preserved (no change).

Verified paths:
- BEV unaffected: entire block gated by _is_phev (BEVs take the
  elif-is_charging path which already has sync-up-only protection)
- Bug 1 trace: header=5 sets display to 5, session data preserved;
  charging.level=45 then syncs up cleanly. Entity never sees flicker
  (same async context, debounce fires after both processed)
- Bug 2 trace: header=56 with predicted=58 syncs display down but
  keeps anchor_soc=3 and total_energy_kwh=8.5; end_session reads
  soc_gain=56-3=53% with real energy — session preserved for learning
- Monotonicity guard: after sync-down sets session.last_predicted_soc
  low, next get_predicted_soc computes anchor+energy and max() picks
  the real prediction — display self-corrects on next tick
- Not-charging: full reset unchanged (anchor + energy zeroed)
- PHEV detection: i4 eDrive40 (BEV) safe — _is_metadata_bev override
  prevents misclassification even with erroneous fuel descriptors
@renaudallard
Copy link
Copy Markdown
Contributor Author

Should solve #242

@kvanbiesen kvanbiesen merged commit d0144c4 into kvanbiesen:main Feb 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants