Skip to content

Commit

Permalink
Update vehicles attributes instead of replacing vehicle
Browse files Browse the repository at this point in the history
  • Loading branch information
rikroe committed Nov 17, 2021
1 parent 47c62b0 commit db6cf98
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 19 deletions.
11 changes: 6 additions & 5 deletions bimmer_connected/account.py
Expand Up @@ -295,7 +295,12 @@ def _get_vehicles(self) -> None:
)

for vehicle_dict in response.json():
vehicles.append(ConnectedDriveVehicle(self, vehicle_dict))
# If vehicle already exists, just update it's state
existing_vehicle = self.get_vehicle(vehicle_dict["vin"])
if existing_vehicle:
existing_vehicle.update_state(vehicle_dict)
else:
vehicles.append(ConnectedDriveVehicle(self, vehicle_dict))
self._vehicles = vehicles

def get_vehicle(self, vin: str) -> ConnectedDriveVehicle:
Expand All @@ -317,10 +322,6 @@ def update_vehicle_states(self) -> None:
"""
# With MyBMW, we only have to get the vehicles list.
self._get_vehicles()
# Still calling `update_state` for each vehicle in case we will have
# vehicle-specific endpoints again.
for car in self.vehicles:
car.update_state()
for listener in self._update_listeners:
listener()

Expand Down
19 changes: 10 additions & 9 deletions bimmer_connected/vehicle.py
Expand Up @@ -75,19 +75,20 @@ class ConnectedDriveVehicle(SerializableBaseClass):

def __init__(self, account: "ConnectedDriveAccount", vehicle_dict: dict) -> None:
self._account = account
self.attributes = {k: v for k, v in vehicle_dict.items() if k not in [SERVICE_STATUS, SERVICE_PROPERTIES]}
self.status = VehicleStatus(
{k: v for k, v in vehicle_dict.items() if k in [SERVICE_STATUS, SERVICE_PROPERTIES]}
)
self.remote_services = RemoteServices(account, self)
self.attributes = None
self.status = None
self.remote_services = RemoteServices(self._account, self)
self.observer_latitude = 0.0 # type: float
self.observer_longitude = 0.0 # type: float

@staticmethod
def update_state() -> None:
self.update_state(vehicle_dict)

def update_state(self, vehicle_dict) -> None:
"""Update the state of a vehicle."""
# Updating single vehicle state is currently not needed with MyBMW API.
pass # pylint: disable=unnecessary-pass
self.attributes = {k: v for k, v in vehicle_dict.items() if k not in [SERVICE_STATUS, SERVICE_PROPERTIES]}
self.status = VehicleStatus(
{k: v for k, v in vehicle_dict.items() if k in [SERVICE_STATUS, SERVICE_PROPERTIES]}
)

@property
def charging_profile(self) -> ChargingProfile:
Expand Down
2 changes: 1 addition & 1 deletion bimmer_connected/vehicle_status.py
Expand Up @@ -398,7 +398,7 @@ def charging_status(self) -> ChargingState:
@backend_parameter
def charging_time_remaining(self) -> datetime.timedelta:
"""Get the remaining charging time."""
return round(self._fuel_indicators.remaining_charging_time / 60.0 / 60.0, 2)
return round((self._fuel_indicators.remaining_charging_time or 0) / 60.0 / 60.0, 2)

@property
@backend_parameter
Expand Down
2 changes: 1 addition & 1 deletion test/responses/G21/json_export.json

Large diffs are not rendered by default.

21 changes: 18 additions & 3 deletions test/test_utils.py
@@ -1,8 +1,11 @@
"""Tests for ConnectedDriveAccount."""
import datetime
import logging
import sys
import unittest
from datetime import datetime, timezone
from unittest.mock import MagicMock
from _pytest.monkeypatch import MonkeyPatch


from bimmer_connected.utils import get_class_property_names, parse_datetime, to_json

Expand All @@ -13,6 +16,9 @@
class TestVehicle(unittest.TestCase):
"""Tests for utils."""

def setUp(self):
self.monkeypatch = MonkeyPatch()

def test_drive_train(self):
"""Tests available attribute."""
vehicle = get_mocked_account().get_vehicle(VIN_G21)
Expand All @@ -37,6 +43,15 @@ def test_drive_train(self):

def test_to_json(self):
"""Test serialization to JSON."""
# Fake datetime.now() first
faked_now = datetime.datetime.now()
faked_now = faked_now.replace(hour=21, minute=28, second=59, microsecond=0)
if sys.version_info < (3, 7):
faked_now = faked_now.replace(tzinfo=None)
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = faked_now
self.monkeypatch.setattr(datetime, "datetime", datetime_mock)

vehicle = get_mocked_account().get_vehicle(VIN_G21)
with open(RESPONSE_DIR / "G21" / "json_export.json", "rb") as file:
expected = file.read().decode("UTF-8")
Expand All @@ -47,8 +62,8 @@ def test_to_json(self):
def test_parse_datetime(self):
"""Test datetime parser."""

dt_with_milliseconds = datetime(2021, 11, 12, 13, 14, 15, 567000, tzinfo=timezone.utc)
dt_without_milliseconds = datetime(2021, 11, 12, 13, 14, 15, tzinfo=timezone.utc)
dt_with_milliseconds = datetime.datetime(2021, 11, 12, 13, 14, 15, 567000, tzinfo=datetime.timezone.utc)
dt_without_milliseconds = datetime.datetime(2021, 11, 12, 13, 14, 15, tzinfo=datetime.timezone.utc)

if sys.version_info < (3, 7):
dt_with_milliseconds = dt_with_milliseconds.replace(tzinfo=None)
Expand Down

0 comments on commit db6cf98

Please sign in to comment.