Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions packages/modules/vehicles/vwid/api.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env python3

import logging
from logging import getLogger
from typing import Union
from modules.vehicles.vwid import libvwid
import aiohttp
import asyncio
import time
from asyncio import new_event_loop, set_event_loop
from time import time, mktime
from datetime import datetime
import json
from json import dumps
from modules.common.store import RAMDISK_PATH
from modules.vehicles.vwid.config import VWId
from modules.vehicles.vwid.socutils import socUtils
Expand All @@ -17,11 +17,12 @@
refreshToken_exp_days = 7 # 7 days before refreshToken expires a new refreshToken shall be stored
initialToken = '1.2.3'

log = logging.getLogger(__name__)
log = getLogger(__name__)


# convert utc timestamp to local time
def utc2local(utc):
epoch = time.mktime(utc.timetuple())
epoch = mktime(utc.timetuple())
offset = datetime.fromtimestamp(epoch) - datetime.utcfromtimestamp(epoch)
return utc + offset

Expand Down Expand Up @@ -79,26 +80,28 @@ async def _fetch_soc(self,
if (self.data):
if self.su.keys_exist(self.data, 'userCapabilities', 'capabilitiesStatus', 'error'):
log.error("Server Error: \n"
+ json.dumps(self.data['userCapabilities']['capabilitiesStatus']['error'],
ensure_ascii=False, indent=4))
+ dumps(self.data['userCapabilities']['capabilitiesStatus']['error'],
ensure_ascii=False, indent=4))

if self.su.keys_exist(self.data, 'charging', 'batteryStatus'):
log.debug("batteryStatus: \n" +
json.dumps(self.data['charging']['batteryStatus'],
ensure_ascii=False, indent=4))
dumps(self.data['charging']['batteryStatus'],
ensure_ascii=False, indent=4))

try:
self.soc = int(self.data['charging']['batteryStatus']['value']['currentSOC_pct'])
self.range = float(self.data['charging']['batteryStatus']['value']['cruisingRangeElectric_km'])
soc_tsZ = self.data['charging']['batteryStatus']['value']['carCapturedTimestamp']
soc_tsdtZ = datetime.strptime(soc_tsZ, ts_fmt + "Z")
soc_tsdtL = utc2local(soc_tsdtZ)
self.soc_tsX = datetime.timestamp(soc_tsdtL)
self.soc_ts = datetime.strftime(soc_tsdtL, ts_fmt)
except Exception as e:
log.exception("soc/range/soc_ts field missing exception: e=" + str(e))
self.soc = 0
self.range = 0.0
self.soc_ts = ""
self.soc_tsX = time()

# decision logic - shall a new refreshToken be stored?
self.store_refreshToken = False
Expand All @@ -107,7 +110,7 @@ async def _fetch_soc(self,
if self.refreshTokenOld != initialToken:
try:
self.expOld, self.expOld_dt = self.su.get_token_expiration(self.refreshTokenOld, date_fmt)
self.now = int(time.time())
self.now = int(time())
expirationThreshold = self.expOld - refreshToken_exp_days * 86400

if expirationThreshold < self.now:
Expand Down Expand Up @@ -142,17 +145,17 @@ async def _fetch_soc(self,
if (self.w.tokens['accessToken'] != self.accessTokenOld): # modified accessToken?
self.su.write_token_file(self.accessTokenFile, self.w.tokens['accessToken'])

return self.soc, self.range, self.soc_ts
return self.soc, self.range, self.soc_ts, self.soc_tsX


def fetch_soc(conf: VWId, vehicle: int) -> Union[int, float, str]:

# prepare and call async method
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop = new_event_loop()
set_event_loop(loop)

# get soc, range from server
a = api()
soc, range, soc_ts = loop.run_until_complete(a._fetch_soc(conf, vehicle))
soc, range, soc_ts, soc_tsX = loop.run_until_complete(a._fetch_soc(conf, vehicle))

return soc, range, soc_ts
return soc, range, soc_ts, soc_tsX
4 changes: 3 additions & 1 deletion packages/modules/vehicles/vwid/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ def __init__(self,
user_id: Optional[str] = None, # show in UI
password: Optional[str] = None, # show in UI
vin: Optional[str] = None, # show in UI
refreshToken: Optional[str] = None # DON'T show in UI!
refreshToken: Optional[str] = None, # DON'T show in UI!
calculate_soc: bool = False # show in UI
):
self.user_id = user_id
self.password = password
self.vin = vin
self.refreshToken = refreshToken
self.calculate_soc = calculate_soc


class VWId:
Expand Down
9 changes: 6 additions & 3 deletions packages/modules/vehicles/vwid/soc.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@


def fetch(vehicle_update_data: VehicleUpdateData, config: VWId, vehicle: int) -> CarState:
soc, range, soc_ts = api.fetch_soc(config, vehicle)
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, range)
return CarState(soc=soc, range=range, soc_timestamp=soc_tsX)


def create_vehicle(vehicle_config: VWId, vehicle: int):
def updater(vehicle_update_data: VehicleUpdateData) -> CarState:
return fetch(vehicle_update_data, vehicle_config, vehicle)
return ConfigurableVehicle(vehicle_config=vehicle_config, component_updater=updater, vehicle=vehicle)
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):
Expand Down
Loading