diff --git a/packages/modules/vehicles/vwid/api.py b/packages/modules/vehicles/vwid/api.py deleted file mode 100755 index 30d69946b9..0000000000 --- a/packages/modules/vehicles/vwid/api.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 - -import aiohttp -from asyncio import new_event_loop, set_event_loop -from typing import Union -from modules.vehicles.vwid import libvwid -from modules.vehicles.vwid.config import VWId -from modules.vehicles.vwgroup.vwgroup import VwGroup - - -class api(VwGroup): - - def __init__(self, conf: VWId, vehicle: int): - super().__init__(conf, vehicle) - - # async method, called from sync fetch_soc, required because libvwid expect async environment - async def _fetch_soc(self) -> Union[int, float, str]: - async with aiohttp.ClientSession() as self.session: - vwid = libvwid.vwid(self.session) - return await super().request_data(vwid) - - -def fetch_soc(conf: VWId, vehicle: int) -> Union[int, float, str]: - - # prepare and call async method - loop = new_event_loop() - set_event_loop(loop) - - # get soc, range from server - a = api(conf, vehicle) - soc, range, soc_ts, soc_tsX = loop.run_until_complete(a._fetch_soc()) - - return soc, range, soc_ts, soc_tsX diff --git a/packages/modules/vehicles/vwid/libvwid.py b/packages/modules/vehicles/vwid/libvwid.py index ebfa1768b3..74ddaf5256 100755 --- a/packages/modules/vehicles/vwid/libvwid.py +++ b/packages/modules/vehicles/vwid/libvwid.py @@ -1391,10 +1391,14 @@ async def validate_login(self): return True -class vwid: +class vwid(): + + connection = {} + def __init__(self, session): self.session = session - self.log = logging.getLogger(__name__) + # self.log = logging.getLogger(__name__) + # self.connection = {} def set_vin(self, vin): self.vin = vin @@ -1407,75 +1411,81 @@ def set_jobs(self, jobs): self.jobs_string = ','.join(jobs) async def get_status(self): - global connection - async with aiohttp.ClientSession(headers={'Connection': 'keep-alive'}) as session: - _now = datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ') - data = {} - data['charging'] = {} - data['charging']['batteryStatus'] = {} - data['charging']['batteryStatus']['value'] = {} - data['charging']['batteryStatus']['value']['currentSOC_pct'] = str(0) - data['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] = str(0) - data['charging']['batteryStatus']['value']['carCapturedTimestamp'] = _now - - if 'connection' not in globals() or connection is None: - connection = {} - if self.username not in connection or connection[self.username] != self.username: - _LOGGER.debug("create new connection") - connection[self.username] = Connection(session, self.username, self.password) - connection[self.username]._session_tokens['identity'] = {} - connection[self.username]._session_tokens['Legacy'] = {} - for token in self.tokens: - connection[self.username]._session_tokens['identity'][token] = self.tokens[token] - connection[self.username]._session_tokens['Legacy'][token] = self.tokens[token] - _conn_reuse = False - else: - _LOGGER.debug("reuse existing connection") - connection[self.username]._session = session - _conn_reuse = True - try: - if not _conn_reuse: - _doLogin_result = await connection[self.username].doLogin() - _LOGGER.debug("after 1st doLogin, result=" + str(_doLogin_result)) - if _doLogin_result: - _update_result = True - else: - _update_result = await connection[self.username].update() - _LOGGER.debug("after 1st connection.update without doLogin, result=" + str(_update_result)) - if not _update_result: - _doLogin_result = await connection[self.username].doLogin() - _LOGGER.debug("after 2nd doLogin, result=" + str(_doLogin_result)) + try: + async with aiohttp.ClientSession(headers={'Connection': 'keep-alive'}) as session: + _now = datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ') + data = {} + data['charging'] = {} + data['charging']['batteryStatus'] = {} + data['charging']['batteryStatus']['value'] = {} + data['charging']['batteryStatus']['value']['currentSOC_pct'] = str(0) + data['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] = str(0) + data['charging']['batteryStatus']['value']['carCapturedTimestamp'] = _now + + try: + _k = str(vwid.connection.keys()) + _LOGGER.info(f"libvwid.get_status connections at entry: vwid.connections.keys={_k}") + if self.username not in vwid.connection: + _LOGGER.info(f"create new connection, key={self.username}") + vwid.connection[self.username] = Connection(session, self.username, self.password) + self._connection = vwid.connection[self.username] + vwid.connection[self.username]._session_tokens['identity'] = {} + vwid.connection[self.username]._session_tokens['Legacy'] = {} + for token in self.tokens: + vwid.connection[self.username]._session_tokens['identity'][token] = self.tokens[token] + vwid.connection[self.username]._session_tokens['Legacy'][token] = self.tokens[token] + _conn_reuse = False + else: + _LOGGER.info(f"reuse existing connection, key={self.username}") + vwid.connection[self.username]._session = session + _conn_reuse = True + if not _conn_reuse: + _doLogin_result = await vwid.connection[self.username].doLogin() + _LOGGER.debug("after 1st doLogin, result=" + str(_doLogin_result)) if _doLogin_result: - _update_result = await connection[self.username].update() - _LOGGER.debug("after 2nd connection.update, result=" + str(_update_result)) - else: - _LOGGER.debug("retry doLogin failed, exit") - return data - if _update_result: - _LOGGER.debug("update/doLogin look OK, get results") - for vehicle in connection[self.username].vehicles: - _LOGGER.debug("vehicle loop: " + str(vehicle) + ", self.vin=" + str(self.vin)) - if str(vehicle) == str(self.vin): - _LOGGER.debug("vehicle loop match: " + str(vehicle) + ", self.vin=" + str(self.vin)) - soc = vehicle._states['charging']['batteryStatus']['value']['currentSOC_pct'] - range = vehicle._states['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] - ts = vehicle._states['charging']['batteryStatus']['value']['carCapturedTimestamp'] - _LOGGER.debug("vehicle =" + str(vehicle)) - _LOGGER.debug("soc =" + str(soc)) - _LOGGER.debug("range =" + str(range)) - _LOGGER.debug("timestamp=" + str(ts)) - tsxx = ts.strftime('%Y-%m-%dT%H:%M:%SZ') - _LOGGER.debug("timestampxx=" + str(tsxx)) - data['charging']['batteryStatus']['value']['currentSOC_pct'] = str(soc) - data['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] = str(range) - data['charging']['batteryStatus']['value']['carCapturedTimestamp'] = str(tsxx) - _LOGGER.debug("return data =" + to_json(data, indent=4)) - for token in connection[self.username]._session_tokens['identity']: - self.tokens[token] = connection[self.username]._session_tokens['identity'][token] - return data - else: - _LOGGER.warning("get_status rsp. update failed, return soc 0") - return data - except Exception as error: - _LOGGER.exception("get_status failed, return soc 0, exception=" + str(error)) - return data + _update_result = True + else: + _update_result = await vwid.connection[self.username].update() + _LOGGER.debug("after 1st connection.update without doLogin, result=" + str(_update_result)) + if not _update_result: + _doLogin_result = await vwid.connection[self.username].doLogin() + _LOGGER.debug("after 2nd doLogin, result=" + str(_doLogin_result)) + if _doLogin_result: + _update_result = await vwid.connection[self.username].update() + _LOGGER.debug("after 2nd connection.update, result=" + str(_update_result)) + else: + _LOGGER.error("retry doLogin failed, exit") + raise Exception("Login failed") + if _update_result: + _LOGGER.debug("update/doLogin look OK, get results") + for vehicle in vwid.connection[self.username].vehicles: + _LOGGER.debug("vehicle loop: " + str(vehicle) + ", self.vin=" + str(self.vin)) + if str(vehicle) == str(self.vin): + _LOGGER.debug("vehicle loop match: " + str(vehicle) + ", self.vin=" + str(self.vin)) + soc = vehicle._states['charging']['batteryStatus']['value']['currentSOC_pct'] + range =\ + vehicle._states['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] + ts = vehicle._states['charging']['batteryStatus']['value']['carCapturedTimestamp'] + _LOGGER.debug("vehicle =" + str(vehicle)) + _LOGGER.debug("soc =" + str(soc)) + _LOGGER.debug("range =" + str(range)) + _LOGGER.debug("timestamp=" + str(ts)) + tsxx = ts.strftime('%Y-%m-%dT%H:%M:%SZ') + _LOGGER.debug("timestampxx=" + str(tsxx)) + data['charging']['batteryStatus']['value']['currentSOC_pct'] = str(soc) + data['charging']['batteryStatus']['value']['cruisingRangeElectric_km'] = str(range) + data['charging']['batteryStatus']['value']['carCapturedTimestamp'] = str(tsxx) + _LOGGER.debug("return data =" + to_json(data, indent=4)) + for token in vwid.connection[self.username]._session_tokens['identity']: + self.tokens[token] =\ + vwid.connection[self.username]._session_tokens['identity'][token] + return data + else: + _LOGGER.error("get_status rsp. update failed, raise exception") + raise Exception("get_status: keine Daten empfangen") + except Exception as error: + _LOGGER.exception("get_status failed 1, raise exception, exception=" + str(error)) + raise Exception(error) + except Exception as error: + _LOGGER.exception("get_status failed 0, raise exception=" + str(error)) + raise Exception(error) diff --git a/packages/modules/vehicles/vwid/soc.py b/packages/modules/vehicles/vwid/soc.py index 0042072c44..57e31d4c2f 100755 --- a/packages/modules/vehicles/vwid/soc.py +++ b/packages/modules/vehicles/vwid/soc.py @@ -1,43 +1,41 @@ -from typing import List - +import aiohttp import logging +from asyncio import new_event_loop, set_event_loop +from typing import Union -from helpermodules.cli import run_using_positional_cli_args -from modules.common import store from modules.common.abstract_device import DeviceDescriptor from modules.common.abstract_vehicle import VehicleUpdateData from modules.common.component_state import CarState from modules.common.configurable_vehicle import ConfigurableVehicle -from modules.vehicles.vwid import api -from modules.vehicles.vwid.config import VWId, VWIdConfiguration - +from modules.vehicles.vwid.config import VWId +from modules.vehicles.vwid import libvwid +from modules.vehicles.vwgroup.vwgroup import VwGroup log = logging.getLogger(__name__) -def fetch(vehicle_update_data: VehicleUpdateData, config: VWId, vehicle: int) -> CarState: - soc, range, soc_ts, soc_tsX = api.fetch_soc(config, vehicle) - log.info("Result: soc=" + str(soc)+", range=" + str(range) + "@" + soc_ts) - return CarState(soc=soc, range=range, soc_timestamp=soc_tsX) +def create_vehicle(vehicle_config: VWId, vehicle: int): + def fetch() -> CarState: + nonlocal vw_group + # async method, called from sync fetch_soc, required because libvwid expect async environment + async def _fetch_soc() -> Union[int, float, str]: + async with aiohttp.ClientSession() as session: + return await vw_group.request_data(libvwid.vwid(session)) + + loop = new_event_loop() + set_event_loop(loop) + soc, range, soc_ts, soc_tsX = loop.run_until_complete(_fetch_soc()) + return CarState(soc=soc, range=range, soc_timestamp=soc_tsX) + + vw_group = VwGroup(vehicle_config, vehicle) -def create_vehicle(vehicle_config: VWId, vehicle: int): def updater(vehicle_update_data: VehicleUpdateData) -> CarState: - return fetch(vehicle_update_data, vehicle_config, vehicle) + return fetch() return ConfigurableVehicle(vehicle_config=vehicle_config, component_updater=updater, vehicle=vehicle, calc_while_charging=vehicle_config.configuration.calculate_soc) -def vwid_update(user_id: str, password: str, vin: str, refreshToken: str, charge_point: int): - log.debug("vwid: user_id="+user_id+"vin="+vin+"charge_point="+str(charge_point)) - store.get_car_value_store(charge_point).store.set( - fetch(None, VWId(configuration=VWIdConfiguration(user_id, password, vin, refreshToken)), charge_point)) - - -def main(argv: List[str]): - run_using_positional_cli_args(vwid_update, argv) - - device_descriptor = DeviceDescriptor(configuration_factory=VWId)