Skip to content

Commit 78116f5

Browse files
authored
Merge pull request #374 from renaudallard/main
Flush pending charging energy before SOC re-anchor
2 parents 2ff0f60 + 7db0d05 commit 78116f5

2 files changed

Lines changed: 17 additions & 0 deletions

File tree

custom_components/cardata/soc_prediction.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ def update_bmw_soc(
437437
session.last_energy_update = time.time()
438438
else:
439439
# Charging, from real battery (header): full re-anchor downward
440+
session.flush_pending_energy()
440441
old_anchor = session.anchor_soc
441442
ref_time = session.last_energy_update or session.anchor_timestamp.timestamp()
442443
session.anchor_soc = soc
@@ -458,6 +459,7 @@ def update_bmw_soc(
458459
self._last_predicted_soc[vin] = soc
459460
session = self._sessions.get(vin)
460461
if session is not None:
462+
session.flush_pending_energy()
461463
old_anchor = session.anchor_soc
462464
ref_time = session.last_energy_update or session.anchor_timestamp.timestamp()
463465
session.anchor_soc = soc
@@ -479,6 +481,7 @@ def update_bmw_soc(
479481
# consistent state (prevents race with SyncWorker reads)
480482
session = self._sessions.get(vin)
481483
if session is not None:
484+
session.flush_pending_energy()
482485
old_anchor = session.anchor_soc
483486
ref_time = session.last_energy_update or session.anchor_timestamp.timestamp()
484487
session.anchor_soc = soc

custom_components/cardata/soc_types.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from __future__ import annotations
2929

3030
import logging
31+
import time
3132
from dataclasses import dataclass, field
3233
from datetime import datetime
3334
from typing import Any
@@ -442,3 +443,16 @@ def accumulate_energy(self, power_kw: float, aux_power_kw: float, timestamp: flo
442443
self.last_power_kw = power_kw
443444
self.last_aux_kw = aux_power_kw
444445
self.last_energy_update = timestamp
446+
447+
def flush_pending_energy(self, now: float | None = None) -> None:
448+
"""Credit energy delivered at last known power up to ``now``.
449+
450+
Called before a re-anchor so the energy accrued between the last
451+
power telemetry update and the re-anchor moment is captured in
452+
session_total_energy_kwh instead of being silently dropped when
453+
last_energy_update is fast-forwarded to "now". No-op when there is
454+
no previous power reading to extrapolate from.
455+
"""
456+
if self.last_power_kw <= 0 or self.last_energy_update is None:
457+
return
458+
self.accumulate_energy(self.last_power_kw, self.last_aux_kw, now if now is not None else time.time())

0 commit comments

Comments
 (0)