Skip to content

Commit

Permalink
Merge pull request #49 from CJNE/dev
Browse files Browse the repository at this point in the history
Permission checks and reduce API calls
  • Loading branch information
CJNE authored Nov 26, 2021
2 parents d39387d + 9459819 commit cb54e55
Show file tree
Hide file tree
Showing 7 changed files with 394 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repos:
entry: reorder-python-imports
language: system
types: [python]
args: [--application-directories=custom_components]
args: [--application-directories=custom_components --src=./]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.2.1
hooks:
Expand Down
50 changes: 32 additions & 18 deletions custom_components/porscheconnect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,15 @@ def getDataByVIN(self, vin, key):
# return None
return getFromDict(self.data.get(vin, {}), key)

async def _update_data_for_vin(self, vin):
async def _update_data_for_vehicle(self, vehicle):
vin = vehicle["vin"]
model = vehicle["capabilities"]["carModel"]
vdata = {
**await self.controller.getPosition(vin),
**await self.controller.getStoredOverview(vin),
**await self.controller.getEmobility(vin),
**await self.controller.getEmobility(vin, model),
}
if vehicle["services"]["vehicleServiceEnabledMap"]["CF"] == "ENABLED":
vdata.update(await self.controller.getPosition(vin))
return vdata

async def _async_update_data(self):
Expand All @@ -146,26 +149,36 @@ async def _async_update_data(self):
access_tokens = await self.controller.getAllTokens()
_async_save_tokens(self.hass, self.config_entry, access_tokens)

data = {}
try:
if self.vehicles is None:
self.vehicles = await self.controller.getVehicles()
self.vehicles = []
all_vehicles = await self.controller.getVehicles()

for vehicle in self.vehicles:
summary = await self.controller.getSummary(vehicle["vin"])
for vehicle in all_vehicles:
vin = vehicle["vin"]
if not await self.controller.isAllowed(vin):
_LOGGER.warning(
"User is not granted access to vehicle VIN %s", vin
)
continue
summary = await self.controller.getSummary(vin)
_LOGGER.debug("Fetching initial data for vehicle %s", vin)
vehicle["name"] = summary["nickName"] or summary["modelDescription"]
vehicle["capabilities"] = await self.controller.getCapabilities(vin)
vehicle["services"] = await self.controller.getServices(vin)
# Find out what sensors are supported and store in vehicle
vdata = {}
vin = vehicle["vin"]
vdata = await self._update_data_for_vin(vin)
vdata = await self._update_data_for_vehicle(vehicle)
vehicle["components"] = {
"sensor": [],
"switch": [],
"lock": [],
"binary_sensor": [],
}
for sensor_meta in DATA_MAP:
data = getFromDict(vdata, sensor_meta.key)
if data is not None:
sensor_data = getFromDict(vdata, sensor_meta.key)
if sensor_data is not None:
ha_type = "sensor"
if isinstance(sensor_meta, SwitchMeta):
ha_type = "switch"
Expand All @@ -176,15 +189,16 @@ async def _async_update_data(self):
vehicle["components"][ha_type].append(sensor_meta)

_LOGGER.debug(f"Found vehicle {vehicle['name']}")
_LOGGER.debug(f"Supported components {vehicle['components']}")

data = {}
async with async_timeout.timeout(30):
for vehicle in self.vehicles:
vin = vehicle["vin"]
vdata = await self._update_data_for_vin(vin)
_LOGGER.debug(vehicle)
self.vehicles.append(vehicle)
data[vin] = vdata
# _LOGGER.debug(data)
else:
async with async_timeout.timeout(30):
for vehicle in self.vehicles:
vin = vehicle["vin"]
vdata = await self._update_data_for_vehicle(vehicle)
data[vin] = vdata
# _LOGGER.debug(data)
except PorscheException as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
return data
Expand Down
4 changes: 2 additions & 2 deletions custom_components/porscheconnect/manifest.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"domain": "porscheconnect",
"name": "Porsche Connect",
"version": "0.0.3",
"version": "0.0.4",
"issue_tracker": "https://github.com/CJNE/ha-porscheconnect/issues",
"config_flow": true,
"documentation": "https://github.com/CJNE/ha-porscheconnect",
"requirements": ["pyporscheconnectapi==0.0.14"],
"requirements": ["pyporscheconnectapi==0.0.15"],
"dependencies": [],
"iot_class": "cloud_polling",
"codeowners": ["@cjne"]
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ force_sort_within_sections = true
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
default_section = THIRDPARTY
known_first_party = custom_components.porscheconnect, tests
known_third_party = pyporscheconnectapi
known_local_folder=pyporscheconnectapi
combine_as_imports = true

[tool:pytest]
Expand Down
21 changes: 18 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,22 @@ def auto_enable_custom_integrations(
def mock_connection():
"""Prevent setup."""

from .fixtures.taycan import GET
from .fixtures.taycan import GET, POST

async def mock_get(self, url, params=None):
print(f"GET {url}")
print(params)
return GET.get(url, {})
ret = GET.get(url, {})
print(ret)
return ret

async def mock_post(self, url, data=None, json=None):
print(f"POST {url}")
print(data)
print(json)
return {}
ret = POST.get(url)
print(ret)
return ret

async def mock_tokens(self, application, wasExpired=False):
print(f"Request token {application}")
Expand All @@ -64,6 +68,17 @@ async def mock_tokens(self, application, wasExpired=False):
yield


@pytest.fixture
def mock_noaccess():
"""Return a mocked client object."""

async def mock_access(self, vin):
return False

with patch("custom_components.porscheconnect.Client.isAllowed", mock_access):
yield


@pytest.fixture
def mock_lock_lock():
"""Return a mocked client object."""
Expand Down
Loading

0 comments on commit cb54e55

Please sign in to comment.