Fix app crash on credential refresh

This commit is contained in:
Dielee
2023-06-29 15:15:49 +02:00
parent 47357fb582
commit 241b2f7ba4
+398 -392
View File
@@ -1,392 +1,398 @@
import requests import requests
import mqtt import mqtt
import util import util
from datetime import datetime, timedelta from datetime import datetime, timedelta
from config import settings from config import settings
from babel.dates import format_datetime from babel.dates import format_datetime
from const import charging_system_states, charging_connection_states, door_states, window_states, \ from const import charging_system_states, charging_connection_states, door_states, window_states, \
OAUTH_URL, VEHICLES_URL, VEHICLE_DETAILS_URL, RECHARGE_STATE_URL, CLIMATE_START_URL, \ OAUTH_URL, VEHICLES_URL, VEHICLE_DETAILS_URL, RECHARGE_STATE_URL, CLIMATE_START_URL, \
WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, supported_entities, BATTERY_CHARGE_STATE_URL, \ WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, supported_entities, BATTERY_CHARGE_STATE_URL, \
STATISTICS_URL STATISTICS_URL
session = requests.Session() session = requests.Session()
session.headers = { session.headers = {
"vcc-api-key": settings["volvoData"]["vccapikey"], "vcc-api-key": settings["volvoData"]["vccapikey"],
"content-type": "application/json", "content-type": "application/json",
"accept": "*/*" "accept": "*/*"
} }
token_expires_at: datetime token_expires_at: datetime
refresh_token = None refresh_token = None
vins = [] vins = []
supported_endpoints = {} supported_endpoints = {}
cached_requests = {} cached_requests = {}
def authorize(): def authorize():
headers = { headers = {
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=", "authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
"content-type": "application/x-www-form-urlencoded", "content-type": "application/x-www-form-urlencoded",
"accept": "application/json" "accept": "application/json"
} }
body = { body = {
"username": settings.volvoData["username"], "username": settings.volvoData["username"],
"password": settings.volvoData["password"], "password": settings.volvoData["password"],
"grant_type": "password", "grant_type": "password",
"scope": "openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes" "scope": "openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes"
} }
auth = requests.post(OAUTH_URL, data=body, headers=headers) auth = requests.post(OAUTH_URL, data=body, headers=headers)
if auth.status_code == 200: if auth.status_code == 200:
data = auth.json() data = auth.json()
session.headers.update({'authorization': "Bearer " + data["access_token"]}) session.headers.update({'authorization': "Bearer " + data["access_token"]})
global token_expires_at, refresh_token global token_expires_at, refresh_token
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30)) token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
refresh_token = data["refresh_token"] refresh_token = data["refresh_token"]
get_vehicles() get_vehicles()
check_supported_endpoints() check_supported_endpoints()
else: else:
message = auth.json() message = auth.json()
raise Exception(message["error_description"]) raise Exception(message["error_description"])
def refresh_auth(): def refresh_auth():
print("Refreshing credentials") print("Refreshing credentials")
global refresh_token global refresh_token
headers = { headers = {
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=", "authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
"content-type": "application/x-www-form-urlencoded", "content-type": "application/x-www-form-urlencoded",
"accept": "application/json" "accept": "application/json"
} }
body = { body = {
"grant_type": "refresh_token", "grant_type": "refresh_token",
"refresh_token": refresh_token "refresh_token": refresh_token
} }
auth = requests.post(OAUTH_URL, data=body, headers=headers)
if auth.status_code == 200: try:
data = auth.json() auth = requests.post(OAUTH_URL, data=body, headers=headers)
session.headers.update({'authorization': "Bearer " + data["access_token"]}) except requests.exceptions.RequestException as e:
print("Error refreshing credentials data: " + str(e))
global token_expires_at return None
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
refresh_token = data["refresh_token"] if auth.status_code == 200:
data = auth.json()
session.headers.update({'authorization': "Bearer " + data["access_token"]})
def get_vehicles():
global vins global token_expires_at
if not settings.volvoData["vin"]: token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
vehicles = session.get(VEHICLES_URL) refresh_token = data["refresh_token"]
if vehicles.status_code == 200:
data = vehicles.json()
if len(data["data"]) > 0: def get_vehicles():
for vehicle in data["data"]: global vins
vins.append(vehicle["vin"]) if not settings.volvoData["vin"]:
else: vehicles = session.get(VEHICLES_URL)
raise Exception("No vehicle in account " + settings.volvoData["username"] + " found.") if vehicles.status_code == 200:
else: data = vehicles.json()
error = vehicles.json() if len(data["data"]) > 0:
raise Exception( for vehicle in data["data"]:
"Error getting vehicles: " + str(vehicles.status_code) + ". " + str(error["error"].get("message"))) vins.append(vehicle["vin"])
else: else:
if isinstance(settings.volvoData["vin"], list): raise Exception("No vehicle in account " + settings.volvoData["username"] + " found.")
# If setting is a list, copy else:
vins = settings.volvoData["vin"] error = vehicles.json()
else: raise Exception(
# If setting is a string, append to list "Error getting vehicles: " + str(vehicles.status_code) + ". " + str(error["error"].get("message")))
vins.append(settings.volvoData["vin"]) else:
if isinstance(settings.volvoData["vin"], list):
if len(vins) == 0: # If setting is a list, copy
raise Exception("No vehicle found, exiting application!") vins = settings.volvoData["vin"]
else: else:
initialize_climate(vins) # If setting is a string, append to list
print("Vin: " + str(vins) + " found!") vins.append(settings.volvoData["vin"])
if len(vins) == 0:
def get_vehicle_details(vin): raise Exception("No vehicle found, exiting application!")
response = session.get(VEHICLE_DETAILS_URL.format(vin), timeout=15) else:
if response.status_code == 200: initialize_climate(vins)
data = response.json()["data"] print("Vin: " + str(vins) + " found!")
if "debug" in settings:
if settings["debug"]:
print(response.text) def get_vehicle_details(vin):
device = { response = session.get(VEHICLE_DETAILS_URL.format(vin), timeout=15)
"identifiers": [f"volvoAAOS2mqtt_{vin}"], if response.status_code == 200:
"manufacturer": "Volvo", data = response.json()["data"]
"model": data['descriptions']['model'], if "debug" in settings:
"name": f"{data['descriptions']['model']} ({data['modelYear']}) - {vin}", if settings["debug"]:
} print(response.text)
elif response.status_code == 500 and not settings.volvoData["vin"]: device = {
# Workaround for some cars that are not returning vehicle details "identifiers": [f"volvoAAOS2mqtt_{vin}"],
device = { "manufacturer": "Volvo",
"identifiers": [f"volvoAAOS2mqtt_{vin}"], "model": data['descriptions']['model'],
"manufacturer": "Volvo", "name": f"{data['descriptions']['model']} ({data['modelYear']}) - {vin}",
"model": vin, }
"name": f"Volvo - {vin}", elif response.status_code == 500 and not settings.volvoData["vin"]:
} # Workaround for some cars that are not returning vehicle details
else: device = {
raise Exception("Getting vehicle details failed. Status Code: " + str(response.status_code) + "identifiers": [f"volvoAAOS2mqtt_{vin}"],
". Error: " + response.text) "manufacturer": "Volvo",
"model": vin,
return device "name": f"Volvo - {vin}",
}
else:
def check_supported_endpoints(): raise Exception("Getting vehicle details failed. Status Code: " + str(response.status_code) +
global supported_endpoints ". Error: " + response.text)
for vin in vins:
supported_endpoints[vin] = [] return device
for entity in supported_entities:
if entity["id"] == "battery_charge_level" and entity["url"] == BATTERY_CHARGE_STATE_URL \
and any("battery_charge_level" in d["id"] for d in supported_endpoints[vin]): def check_supported_endpoints():
# If battery charge level could be found in recharge-api, skip the second battery charge sensor global supported_endpoints
continue for vin in vins:
supported_endpoints[vin] = []
if entity.get('url'): for entity in supported_entities:
state = api_call(entity["url"], "GET", vin, entity["id"]) if entity["id"] == "battery_charge_level" and entity["url"] == BATTERY_CHARGE_STATE_URL \
else: and any("battery_charge_level" in d["id"] for d in supported_endpoints[vin]):
state = "" # If battery charge level could be found in recharge-api, skip the second battery charge sensor
continue
if state is not None:
print("Success! " + entity["name"] + " is supported by your vehicle.") if entity.get('url'):
supported_endpoints[vin].append(entity) state = api_call(entity["url"], "GET", vin, entity["id"])
else: else:
print("Failed, " + entity["name"] + " is unfortunately not supported by your vehicle.") state = ""
if state is not None:
def initialize_climate(vins): print("Success! " + entity["name"] + " is supported by your vehicle.")
for vin in vins: supported_endpoints[vin].append(entity)
mqtt.assumed_climate_state[vin] = "OFF" else:
print("Failed, " + entity["name"] + " is unfortunately not supported by your vehicle.")
def disable_climate(vin):
print("Turning climate off by timer!") def initialize_climate(vins):
mqtt.assumed_climate_state[vin] = "OFF" for vin in vins:
mqtt.update_car_data() mqtt.assumed_climate_state[vin] = "OFF"
def api_call(url, method, vin, sensor_id=None, force_update=False): def disable_climate(vin):
global token_expires_at print("Turning climate off by timer!")
if datetime.now(util.TZ) >= token_expires_at: mqtt.assumed_climate_state[vin] = "OFF"
refresh_auth() mqtt.update_car_data()
if url in [RECHARGE_STATE_URL, WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, STATISTICS_URL]:
# Minimize API calls for endpoints with multiple values def api_call(url, method, vin, sensor_id=None, force_update=False):
response = cached_request(url, method, vin, force_update) global token_expires_at
if response is None: if datetime.now(util.TZ) >= token_expires_at:
# Exception caught while getting data from volvo api, doing nothing refresh_auth()
return None
elif method == "GET": if url in [RECHARGE_STATE_URL, WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, STATISTICS_URL]:
print("Starting " + method + " call against " + url) # Minimize API calls for endpoints with multiple values
try: response = cached_request(url, method, vin, force_update)
response = session.get(url.format(vin), timeout=15) if response is None:
except requests.exceptions.RequestException as e: # Exception caught while getting data from volvo api, doing nothing
print("Error getting data: " + str(e)) return None
return None elif method == "GET":
elif method == "POST": print("Starting " + method + " call against " + url)
print("Starting " + method + " call against " + url) try:
try: response = session.get(url.format(vin), timeout=15)
response = session.post(url.format(vin), timeout=20) except requests.exceptions.RequestException as e:
except requests.exceptions.RequestException as e: print("Error getting data: " + str(e))
print("Error getting data: " + str(e)) return None
return None elif method == "POST":
else: print("Starting " + method + " call against " + url)
print("Unkown method posted: " + method + ". Returning nothing") try:
return None response = session.post(url.format(vin), timeout=20)
except requests.exceptions.RequestException as e:
if response.status_code == 200: print("Error getting data: " + str(e))
data = response.json() return None
if "debug" in settings: else:
if settings["debug"]: print("Unkown method posted: " + method + ". Returning nothing")
print(response.text) return None
else:
if url == CLIMATE_START_URL and response.status_code == 503: if response.status_code == 200:
print("Car in use, cannot start pre climatization") data = response.json()
mqtt.assumed_climate_state[vin] = "OFF" if "debug" in settings:
mqtt.update_car_data() if settings["debug"]:
elif "extended-vehicle" in url and response.status_code == 403: print(response.text)
# Suppress 403 errors for unsupported extended-vehicle api cars else:
return None if url == CLIMATE_START_URL and response.status_code == 503:
else: print("Car in use, cannot start pre climatization")
print("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text) mqtt.assumed_climate_state[vin] = "OFF"
return None mqtt.update_car_data()
return parse_api_data(data, sensor_id) elif "extended-vehicle" in url and response.status_code == 403:
# Suppress 403 errors for unsupported extended-vehicle api cars
return None
def cached_request(url, method, vin, force_update=False): else:
global cached_requests print("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text)
if not util.keys_exists(cached_requests, vin + "_" + url): return None
# No API Data cached, get fresh data from API return parse_api_data(data, sensor_id)
print("Starting " + method + " call against " + url)
try:
response = session.get(url.format(vin), timeout=15) def cached_request(url, method, vin, force_update=False):
except requests.exceptions.RequestException as e: global cached_requests
print("Error getting data: " + str(e)) if not util.keys_exists(cached_requests, vin + "_" + url):
return None # No API Data cached, get fresh data from API
print("Starting " + method + " call against " + url)
data = {"response": response, "last_update": datetime.now(util.TZ)} try:
cached_requests[vin + "_" + url] = data response = session.get(url.format(vin), timeout=15)
else: except requests.exceptions.RequestException as e:
if (datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() \ print("Error getting data: " + str(e))
>= settings["updateInterval"] or (force_update and return None
(datetime.now(util.TZ) - cached_requests[vin + "_" + url]
["last_update"]).total_seconds() >= 2): data = {"response": response, "last_update": datetime.now(util.TZ)}
# Old Data in Cache, or force mode active, updating cached_requests[vin + "_" + url] = data
print("Starting " + method + " call against " + url) else:
try: if (datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() \
response = session.get(url.format(vin), timeout=15) >= settings["updateInterval"] or (force_update and
except requests.exceptions.RequestException as e: (datetime.now(util.TZ) - cached_requests[vin + "_" + url]
print("Error getting data: " + str(e)) ["last_update"]).total_seconds() >= 2):
return None # Old Data in Cache, or force mode active, updating
data = {"response": response, "last_update": datetime.now(util.TZ)} print("Starting " + method + " call against " + url)
cached_requests[vin + "_" + url] = data try:
else: response = session.get(url.format(vin), timeout=15)
# Data is up do date, returning cached data except requests.exceptions.RequestException as e:
response = cached_requests[vin + "_" + url]["response"] print("Error getting data: " + str(e))
return response return None
data = {"response": response, "last_update": datetime.now(util.TZ)}
cached_requests[vin + "_" + url] = data
def parse_api_data(data, sensor_id=None): else:
data = data["data"] # Data is up do date, returning cached data
if sensor_id == "battery_charge_level": response = cached_requests[vin + "_" + url]["response"]
return data["batteryChargeLevel"]["value"] if util.keys_exists(data, "batteryChargeLevel") else None return response
elif sensor_id == "electric_range":
return util.convert_metric_values(data["electricRange"]["value"]) \
if util.keys_exists(data, "electricRange") else None def parse_api_data(data, sensor_id=None):
elif sensor_id == "charging_system_status": data = data["data"]
return charging_system_states[data["chargingSystemStatus"]["value"]] \ if sensor_id == "battery_charge_level":
if util.keys_exists(data, "chargingSystemStatus") else None return data["batteryChargeLevel"]["value"] if util.keys_exists(data, "batteryChargeLevel") else None
elif sensor_id == "charging_connection_status": elif sensor_id == "electric_range":
return charging_connection_states[data["chargingConnectionStatus"]["value"]] \ return util.convert_metric_values(data["electricRange"]["value"]) \
if util.keys_exists(data, "chargingConnectionStatus") else None if util.keys_exists(data, "electricRange") else None
elif sensor_id == "estimated_charging_time": elif sensor_id == "charging_system_status":
if util.keys_exists(data, "chargingSystemStatus"): return charging_system_states[data["chargingSystemStatus"]["value"]] \
charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] if util.keys_exists(data, "chargingSystemStatus") else None
if charging_system_state == "Charging": elif sensor_id == "charging_connection_status":
return data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") else "" return charging_connection_states[data["chargingConnectionStatus"]["value"]] \
else: if util.keys_exists(data, "chargingConnectionStatus") else None
return 0 elif sensor_id == "estimated_charging_time":
else: if util.keys_exists(data, "chargingSystemStatus"):
return None charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]]
elif sensor_id == "estimated_charging_finish_time": if charging_system_state == "Charging":
if util.keys_exists(data, "chargingSystemStatus"): return data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") else ""
charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] else:
if charging_system_state == "Charging": return 0
charging_time = int( else:
data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") return None
else 0) elif sensor_id == "estimated_charging_finish_time":
charging_finished = datetime.now(util.TZ) + timedelta(minutes=charging_time) if util.keys_exists(data, "chargingSystemStatus"):
return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"]) charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]]
else: if charging_system_state == "Charging":
return "" charging_time = int(
else: data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime")
return None else 0)
elif sensor_id == "lock_status": charging_finished = datetime.now(util.TZ) + timedelta(minutes=charging_time)
return data["carLocked"]["value"] if util.keys_exists(data, "carLocked") else None return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"])
elif sensor_id == "odometer": else:
multiplier = 1 return ""
if util.keys_exists(settings["volvoData"], "odometerMultiplier"): else:
multiplier = settings["volvoData"]["odometerMultiplier"] return None
if isinstance(multiplier, str): elif sensor_id == "lock_status":
multiplier = 1 return data["carLocked"]["value"] if util.keys_exists(data, "carLocked") else None
elif multiplier < 1: elif sensor_id == "odometer":
multiplier = 1 multiplier = 1
return util.convert_metric_values(int(data["odometer"]["value"]) * multiplier) \ if util.keys_exists(settings["volvoData"], "odometerMultiplier"):
if util.keys_exists(data, "odometer") else None multiplier = settings["volvoData"]["odometerMultiplier"]
elif sensor_id == "window_front_left": if isinstance(multiplier, str):
return window_states[data["frontLeftWindowOpen"]["value"]] if util.keys_exists(data, "frontLeftWindowOpen") \ multiplier = 1
else None elif multiplier < 1:
elif sensor_id == "window_front_right": multiplier = 1
return window_states[data["frontRightWindowOpen"]["value"]] if util.keys_exists(data, "frontRightWindowOpen") \ return util.convert_metric_values(int(data["odometer"]["value"]) * multiplier) \
else None if util.keys_exists(data, "odometer") else None
elif sensor_id == "window_rear_left": elif sensor_id == "window_front_left":
return window_states[data["rearLeftWindowOpen"]["value"]] if util.keys_exists(data, "rearLeftWindowOpen") \ return window_states[data["frontLeftWindowOpen"]["value"]] if util.keys_exists(data, "frontLeftWindowOpen") \
else None else None
elif sensor_id == "window_rear_right": elif sensor_id == "window_front_right":
return window_states[data["rearRightWindowOpen"]["value"]] if util.keys_exists(data, "rearRightWindowOpen") \ return window_states[data["frontRightWindowOpen"]["value"]] if util.keys_exists(data, "frontRightWindowOpen") \
else None else None
elif sensor_id == "door_front_left": elif sensor_id == "window_rear_left":
return door_states[data["frontLeftDoorOpen"]["value"]] if util.keys_exists(data, "frontLeftDoorOpen") else None return window_states[data["rearLeftWindowOpen"]["value"]] if util.keys_exists(data, "rearLeftWindowOpen") \
elif sensor_id == "door_front_right": else None
return door_states[data["frontRightDoorOpen"]["value"]] \ elif sensor_id == "window_rear_right":
if util.keys_exists(data, "frontRightDoorOpen") else None return window_states[data["rearRightWindowOpen"]["value"]] if util.keys_exists(data, "rearRightWindowOpen") \
elif sensor_id == "door_rear_left": else None
return door_states[data["rearLeftDoorOpen"]["value"]] if util.keys_exists(data, "rearLeftDoorOpen") else None elif sensor_id == "door_front_left":
elif sensor_id == "door_rear_right": return door_states[data["frontLeftDoorOpen"]["value"]] if util.keys_exists(data, "frontLeftDoorOpen") else None
return door_states[data["rearRightDoorOpen"]["value"]] if util.keys_exists(data, "rearRightDoorOpen") else None elif sensor_id == "door_front_right":
elif sensor_id == "tailgate": return door_states[data["frontRightDoorOpen"]["value"]] \
return door_states[data["tailGateOpen"]["value"]] if util.keys_exists(data, "tailGateOpen") else None if util.keys_exists(data, "frontRightDoorOpen") else None
elif sensor_id == "sunroof": elif sensor_id == "door_rear_left":
return door_states[data["sunRoofOpen"]["value"]] if util.keys_exists(data, "sunRoofOpen") else None return door_states[data["rearLeftDoorOpen"]["value"]] if util.keys_exists(data, "rearLeftDoorOpen") else None
elif sensor_id == "engine_hood": elif sensor_id == "door_rear_right":
return door_states[data["hoodOpen"]["value"]] if util.keys_exists(data, "hoodOpen") else None return door_states[data["rearRightDoorOpen"]["value"]] if util.keys_exists(data, "rearRightDoorOpen") else None
elif sensor_id == "tank_lid": elif sensor_id == "tailgate":
return door_states[data["tankLidOpen"]["value"]] if util.keys_exists(data, "tankLidOpen") else None return door_states[data["tailGateOpen"]["value"]] if util.keys_exists(data, "tailGateOpen") else None
elif sensor_id == "tyre_front_left": elif sensor_id == "sunroof":
return data["frontLeftTyrePressure"]["value"] if util.keys_exists(data, "frontLeftTyrePressure") else None return door_states[data["sunRoofOpen"]["value"]] if util.keys_exists(data, "sunRoofOpen") else None
elif sensor_id == "tyre_front_right": elif sensor_id == "engine_hood":
return data["frontRightTyrePressure"]["value"] if util.keys_exists(data, "frontRightTyrePressure") else None return door_states[data["hoodOpen"]["value"]] if util.keys_exists(data, "hoodOpen") else None
elif sensor_id == "tyre_rear_left": elif sensor_id == "tank_lid":
return data["rearLeftTyrePressure"]["value"] if util.keys_exists(data, "rearLeftTyrePressure") else None return door_states[data["tankLidOpen"]["value"]] if util.keys_exists(data, "tankLidOpen") else None
elif sensor_id == "tyre_rear_right": elif sensor_id == "tyre_front_left":
return data["rearRightTyrePressure"]["value"] if util.keys_exists(data, "rearRightTyrePressure") else None return data["frontLeftTyrePressure"]["value"] if util.keys_exists(data, "frontLeftTyrePressure") else None
elif sensor_id == "engine_state": elif sensor_id == "tyre_front_right":
return data["engineRunning"]["value"] if util.keys_exists(data, "engineRunning") else None return data["frontRightTyrePressure"]["value"] if util.keys_exists(data, "frontRightTyrePressure") else None
elif sensor_id == "fuel_level": elif sensor_id == "tyre_rear_left":
if util.keys_exists(data, "fuelAmount"): return data["rearLeftTyrePressure"]["value"] if util.keys_exists(data, "rearLeftTyrePressure") else None
fuel_amount = int(data["fuelAmount"]["value"]) elif sensor_id == "tyre_rear_right":
if fuel_amount > 0: return data["rearRightTyrePressure"]["value"] if util.keys_exists(data, "rearRightTyrePressure") else None
return fuel_amount elif sensor_id == "engine_state":
else: return data["engineRunning"]["value"] if util.keys_exists(data, "engineRunning") else None
return None elif sensor_id == "fuel_level":
else: if util.keys_exists(data, "fuelAmount"):
return None fuel_amount = int(data["fuelAmount"]["value"])
elif sensor_id == "average_fuel_consumption": if fuel_amount > 0:
if util.keys_exists(data, "averageFuelConsumption"): return fuel_amount
average_fuel_con = float(data["averageFuelConsumption"]["value"]) else:
if average_fuel_con > 0: return None
multiplier = 1 else:
if util.keys_exists(settings["volvoData"], "averageFuelConsumptionMultiplier"): return None
multiplier = settings["volvoData"]["averageFuelConsumptionMultiplier"] elif sensor_id == "average_fuel_consumption":
if isinstance(multiplier, str): if util.keys_exists(data, "averageFuelConsumption"):
multiplier = 1 average_fuel_con = float(data["averageFuelConsumption"]["value"])
elif multiplier < 1: if average_fuel_con > 0:
multiplier = 1 multiplier = 1
return average_fuel_con * multiplier if util.keys_exists(settings["volvoData"], "averageFuelConsumptionMultiplier"):
else: multiplier = settings["volvoData"]["averageFuelConsumptionMultiplier"]
return None if isinstance(multiplier, str):
else: multiplier = 1
return None elif multiplier < 1:
elif sensor_id == "average_speed": multiplier = 1
if util.keys_exists(data, "averageSpeed"): return average_fuel_con * multiplier
average_speed = int(data["averageSpeed"]["value"]) else:
if average_speed > 1: return None
divider = 1 else:
if util.keys_exists(settings["volvoData"], "averageSpeedDivider"): return None
divider = settings["volvoData"]["averageSpeedDivider"] elif sensor_id == "average_speed":
if isinstance(divider, str): if util.keys_exists(data, "averageSpeed"):
divider = 1 average_speed = int(data["averageSpeed"]["value"])
elif divider < 1: if average_speed > 1:
divider = 1 divider = 1
return util.convert_metric_values(average_speed / divider) if util.keys_exists(settings["volvoData"], "averageSpeedDivider"):
else: divider = settings["volvoData"]["averageSpeedDivider"]
return None if isinstance(divider, str):
else: divider = 1
return None elif divider < 1:
elif sensor_id == "location": divider = 1
coordinates = {} return util.convert_metric_values(average_speed / divider)
if util.keys_exists(data, "geometry"): else:
raw_data = data["geometry"] return None
if util.keys_exists(raw_data, "coordinates"): else:
coordinates = {"longitude": raw_data["coordinates"][0], return None
"latitude": raw_data["coordinates"][1], elif sensor_id == "location":
"gps_accuracy": 1} coordinates = {}
return coordinates if util.keys_exists(data, "geometry"):
elif sensor_id == "distance_to_empty": raw_data = data["geometry"]
return util.convert_metric_values(data["distanceToEmpty"]["value"]) \ if util.keys_exists(raw_data, "coordinates"):
if util.keys_exists(data, "distanceToEmpty") else None coordinates = {"longitude": raw_data["coordinates"][0],
elif sensor_id == "washer_fluid_level": "latitude": raw_data["coordinates"][1],
return data["washerFluidLevel"]["value"] if util.keys_exists(data, "washerFluidLevel") else None "gps_accuracy": 1}
else: return coordinates
return None elif sensor_id == "distance_to_empty":
return util.convert_metric_values(data["distanceToEmpty"]["value"]) \
if util.keys_exists(data, "distanceToEmpty") else None
elif sensor_id == "washer_fluid_level":
return data["washerFluidLevel"]["value"] if util.keys_exists(data, "washerFluidLevel") else None
else:
return None