Skip to content

Commit

Permalink
Fix total range for hybrid vehicles (#515)
Browse files Browse the repository at this point in the history
* Refactor total range calculation

* Split range extender/hybrid total range logic

* Update tests
  • Loading branch information
rikroe authored Feb 5, 2023
1 parent 94ad4ab commit c84bae9
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 12 deletions.
31 changes: 25 additions & 6 deletions bimmer_connected/vehicle/fuel_and_battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from dataclasses import dataclass
from typing import Any, Dict, Optional

from bimmer_connected.const import ATTR_ATTRIBUTES
from bimmer_connected.const import ATTR_ATTRIBUTES, ATTR_STATE
from bimmer_connected.models import StrEnum, ValueWithUnit, VehicleDataBase
from bimmer_connected.vehicle.const import COMBUSTION_ENGINE_DRIVE_TRAINS, HV_BATTERY_DRIVE_TRAINS, DriveTrainType

Expand Down Expand Up @@ -88,7 +88,14 @@ def _parse_vehicle_data(cls, vehicle_data: Dict) -> Optional[Dict]:
retval: Dict[str, Any] = {}
drivetrain = DriveTrainType(vehicle_data.get(ATTR_ATTRIBUTES, {}).get("driveTrain") or DriveTrainType.UNKNOWN)

state = vehicle_data.get("state", {})
# return early if state data hasn't been loaded or no combustion/electric data is available
if (
ATTR_STATE not in vehicle_data
or len({"combustionFuelLevel", "electricChargingState"}.intersection(set(vehicle_data[ATTR_STATE]))) == 0
):
return retval

state = vehicle_data["state"]

if drivetrain in COMBUSTION_ENGINE_DRIVE_TRAINS:
retval.update(cls._parse_fuel_data(state.get("combustionFuelLevel", {}), vehicle_data["is_metric"]))
Expand All @@ -106,12 +113,24 @@ def _parse_vehicle_data(cls, vehicle_data: Dict) -> Optional[Dict]:
)

if drivetrain in set(COMBUSTION_ENGINE_DRIVE_TRAINS).intersection(HV_BATTERY_DRIVE_TRAINS):
# for hybrid vehicles the remaining_range_fuel returned by the API seems to be the total remaining range
# to calculate the correct remaining range on fuel, we have to subtract the remaining electric range
# this does not seem to apply for the old I3 with range extender

fuel: ValueWithUnit = retval.get("remaining_range_fuel", ValueWithUnit(None, None))
electric: ValueWithUnit = retval.get("remaining_range_electric", ValueWithUnit(None, None))
retval["remaining_range_total"] = ValueWithUnit(
(fuel.value or 0) + (electric.value or 0),
fuel.unit or electric.unit,
)

if drivetrain == DriveTrainType.ELECTRIC_WITH_RANGE_EXTENDER:
retval["remaining_range_total"] = ValueWithUnit(
(fuel.value or 0) + (electric.value or 0),
fuel.unit or electric.unit,
)
else:
retval["remaining_range_total"] = retval["remaining_range_fuel"]
retval["remaining_range_fuel"] = ValueWithUnit(
(fuel.value or 0) - (electric.value or 0),
fuel.unit or electric.unit,
)
elif drivetrain in COMBUSTION_ENGINE_DRIVE_TRAINS and "remaining_range_fuel" in retval:
retval["remaining_range_total"] = retval["remaining_range_fuel"]
elif drivetrain in HV_BATTERY_DRIVE_TRAINS and "remaining_range_electric" in retval:
Expand Down
4 changes: 2 additions & 2 deletions test/test_deprecated_vehicle_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ async def test_range_phev(caplog):
status = (await get_mocked_account()).get_vehicle(VIN_G01).status

assert (40, "L") == status.remaining_fuel
assert (476, "km") == status.remaining_range_fuel
assert (436, "km") == status.remaining_range_fuel
assert 80 == status.fuel_percent

assert 80 == status.charging_level_hv
assert (40, "km") == status.remaining_range_electric

assert (516, "km") == status.remaining_range_total
assert (476, "km") == status.remaining_range_total

assert status.remaining_range_fuel[0] + status.remaining_range_electric[0] == status.remaining_range_total[0]

Expand Down
8 changes: 4 additions & 4 deletions test/test_vehicle_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ async def test_range_phev(caplog):
status = (await get_mocked_account()).get_vehicle(VIN_G01).fuel_and_battery

assert (40, "L") == status.remaining_fuel
assert (476, "km") == status.remaining_range_fuel
assert (436, "km") == status.remaining_range_fuel
assert 80 == status.remaining_fuel_percent

assert 80 == status.remaining_battery_percent
assert (40, "km") == status.remaining_range_electric

assert (516, "km") == status.remaining_range_total
assert (476, "km") == status.remaining_range_total

assert status.remaining_range_fuel[0] + status.remaining_range_electric[0] == status.remaining_range_total[0]

Expand All @@ -107,13 +107,13 @@ async def test_range_phev(caplog):
status = (await get_mocked_account(metric=False)).get_vehicle(VIN_G01).fuel_and_battery

assert (40, "gal") == status.remaining_fuel
assert (476, "mi") == status.remaining_range_fuel
assert (436, "mi") == status.remaining_range_fuel
assert 80 == status.remaining_fuel_percent

assert 80 == status.remaining_battery_percent
assert (40, "mi") == status.remaining_range_electric

assert (516, "mi") == status.remaining_range_total
assert (476, "mi") == status.remaining_range_total

assert status.remaining_range_fuel[0] + status.remaining_range_electric[0] == status.remaining_range_total[0]

Expand Down

0 comments on commit c84bae9

Please sign in to comment.