Compare commits

...
6 Commits
6 changed files with 259 additions and 205 deletions
+11 -1
View File
@@ -129,7 +129,17 @@ The following steps are required for authentication in exactly this order:
Just install this addon with the following command. Just install this addon with the following command.
Please note to fill in your settings inside the environment variables. Please note to fill in your settings inside the environment variables.
`docker run -d --pull=always -e CONF_updateInterval=300 -e CONF_babelLocale='de' -e CONF_mqtt='@json {"broker": "", "username": "", "password": "", "port": 1883}' -e CONF_volvoData='@json {"username": "", "password": "", "vin": "", "vccapikey": ["key1", "key2"]}' -e TZ='Europe/Berlin' --name volvo2mqtt ghcr.io/dielee/volvo2mqtt:latest` <pre>
<code>docker run -d --pull=always \
-e CONF_updateInterval=300 \
-e CONF_babelLocale='de' \
-e CONF_mqtt='@json {"broker": "", "username": "", "password": "", "port": 1883}' \
-e CONF_volvoData='@json {"username": "", "password": "", "vin": "", "vccapikey": ["key1", "key2"]}' \
-e TZ='Europe/Berlin' \
--name volvo2mqtt \
ghcr.io/dielee/volvo2mqtt:latest
</code>
</pre>
<b>HA Add-On:</b><br> <b>HA Add-On:</b><br>
+13
View File
@@ -1,3 +1,16 @@
## v1.13.0
### 🚀 Features:
- Move energy api to v2 (https://developer.volvocars.com/apis/energy/v2/release-notes/)
## v1.12.2
### 🚀 Features:
- Add more logging for refresh process
- Update refresh token, if volvo API returns a new one
## v1.12.1 ## v1.12.1
### 🐛 Bug Fixes: ### 🐛 Bug Fixes:
+1 -1
View File
@@ -1,6 +1,6 @@
name: "Volvo2Mqtt" name: "Volvo2Mqtt"
description: "Volvo AAOS MQTT bridge" description: "Volvo AAOS MQTT bridge"
version: "1.12.1" version: "1.13.0"
slug: "volvo2mqtt" slug: "volvo2mqtt"
init: false init: false
url: "https://github.com/Dielee/volvo2mqtt" url: "https://github.com/Dielee/volvo2mqtt"
+7 -8
View File
@@ -1,6 +1,6 @@
from config import settings from config import settings
VERSION = "v1.12.1" VERSION = "v1.13.0"
OAUTH_TOKEN_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2" OAUTH_TOKEN_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
OAUTH_AUTH_URL = "https://volvoid.eu.volvocars.com/as/authorization.oauth2" OAUTH_AUTH_URL = "https://volvoid.eu.volvocars.com/as/authorization.oauth2"
@@ -12,7 +12,7 @@ CLIMATE_STOP_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/
LOCK_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/doors" LOCK_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/doors"
CAR_LOCK_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/lock" CAR_LOCK_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/lock"
CAR_UNLOCK_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/unlock" CAR_UNLOCK_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/unlock"
RECHARGE_STATE_URL = "https://api.volvocars.com/energy/v1/vehicles/{0}/recharge-status" RECHARGE_STATE_URL = "https://api.volvocars.com/energy/v2/vehicles/{0}/state"
ODOMETER_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/odometer" ODOMETER_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/odometer"
LOCATION_STATE_URL = "https://api.volvocars.com/location/v1/vehicles/{0}/location" LOCATION_STATE_URL = "https://api.volvocars.com/location/v1/vehicles/{0}/location"
TYRE_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/tyres" TYRE_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/tyres"
@@ -59,13 +59,12 @@ units = {
availability_topic = "volvoAAOS2mqtt/availability" availability_topic = "volvoAAOS2mqtt/availability"
charging_system_states = {"CHARGING_SYSTEM_CHARGING": "Charging", "CHARGING_SYSTEM_IDLE": "Idle", charging_system_states = {"CHARGING": "Charging", "IDLE": "Idle",
"CHARGING_SYSTEM_FAULT": "Fault", "CHARGING_SYSTEM_UNSPECIFIED": "Unspecified", "FAULT": "Fault", "UNSPECIFIED": "Unspecified",
"CHARGING_SYSTEM_DONE": "Done", "CHARGING_SYSTEM_SCHEDULED": "Scheduled"} "DONE": "Done", "SCHEDULED": "Scheduled"}
charging_connection_states = {"CONNECTION_STATUS_DISCONNECTED": "Disconnected", "CONNECTION_STATUS_UNSPECIFIED": "Unspecified", charging_connection_states = {"DISCONNECTED": "Disconnected", "UNSPECIFIED": "Unspecified",
"CONNECTION_STATUS_CONNECTED_DC": "Connected DC", "CONNECTION_STATUS_CONNECTED_AC": "Connected AC", "FAULT": "Fault", "CONNECTED": "Connected"}
"CONNECTION_STATUS_FAULT": "Fault"}
window_states = {"CLOSED": "OFF", "OPEN": "ON", "UNSPECIFIED": "UNKNOWN", "AJAR": "ON"} window_states = {"CLOSED": "OFF", "OPEN": "ON", "UNSPECIFIED": "UNKNOWN", "AJAR": "ON"}
door_states = {"CLOSED": "OFF", "OPEN": "ON", "UNSPECIFIED": "UNKNOWN", "AJAR": "ON"} door_states = {"CLOSED": "OFF", "OPEN": "ON", "UNSPECIFIED": "UNKNOWN", "AJAR": "ON"}
+14 -1
View File
@@ -176,16 +176,24 @@ def on_message(client, userdata, msg):
if "climate_status" in msg.topic: if "climate_status" in msg.topic:
if payload == "ON": if payload == "ON":
start_climate(vin) start_climate(vin)
return None
elif payload == "OFF": elif payload == "OFF":
stop_climate(vin) stop_climate(vin)
return None
return None
elif "lock_status" in msg.topic: elif "lock_status" in msg.topic:
if payload == "LOCK": if payload == "LOCK":
lock_car(vin) lock_car(vin)
return None
elif payload == "UNLOCK": elif payload == "UNLOCK":
unlock_car(vin) unlock_car(vin)
return None
return None
elif "update_data" in msg.topic: elif "update_data" in msg.topic:
if payload == "PRESS": if payload == "PRESS":
update_car_data(True) update_car_data(True)
return None
return None
elif "update_interval" in msg.topic: elif "update_interval" in msg.topic:
try: try:
update_interval = int(payload) update_interval = int(payload)
@@ -194,8 +202,10 @@ def on_message(client, userdata, msg):
else: else:
logging.warning(f"Interval {update_interval} seconds is to low. Doing nothing!") logging.warning(f"Interval {update_interval} seconds is to low. Doing nothing!")
update_car_data() update_car_data()
return None
except ValueError as error: except ValueError as error:
logging.error(f"Unable to change update_interval {error} payload={payload}") logging.error(f"Unable to change update_interval {error} payload={payload}")
return None
elif "schedule" in msg.topic: elif "schedule" in msg.topic:
try: try:
d = json.loads(payload) d = json.loads(payload)
@@ -205,8 +215,11 @@ def on_message(client, userdata, msg):
if d["mode"] == "timer": if d["mode"] == "timer":
start_climate_timer(d, vin) start_climate_timer(d, vin)
return None
else: else:
logging.warning("No schedule mode found, doing nothing") logging.warning("No schedule mode found, doing nothing")
return None
return None
def start_climate_timer(d, vin): def start_climate_timer(d, vin):
+213 -194
View File
@@ -48,6 +48,10 @@ def authorize(renew_tokenfile=False):
logging.warning("Detected corrupted token file, restarting auth process") logging.warning("Detected corrupted token file, restarting auth process")
authorize(True) authorize(True)
return return
except KeyError:
logging.warning("Token file missing refresh_token, restarting auth process")
authorize(True)
return
else: else:
logging.info("Starting login with OTP") logging.info("Starting login with OTP")
auth_session = requests.session() auth_session = requests.session()
@@ -171,8 +175,9 @@ def send_otp(auth_session, data):
def refresh_auth(): def refresh_auth():
logging.info("Refreshing credentials")
global refresh_token global refresh_token
logging.info("Refreshing credentials with token " + refresh_token)
headers = { headers = {
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=", "authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
"content-type": "application/x-www-form-urlencoded", "content-type": "application/x-www-form-urlencoded",
@@ -192,16 +197,22 @@ def refresh_auth():
if auth.status_code == 200: if auth.status_code == 200:
token_path = util.get_token_path() token_path = util.get_token_path()
if os.path.exists(token_path):
with open(token_path) as f:
data = json.load(f)
refresh_data = auth.json() refresh_data = auth.json()
f = open(token_path) if not "refresh_token" in refresh_data:
try: f = open(token_path)
data = json.load(f) try:
refresh_token = data["refresh_token"] data = json.load(f)
except ValueError: refresh_data["refresh_token"] = data["refresh_token"]
raise Exception("Cannot refresh token!") except ValueError:
raise Exception("Cannot refresh token!")
else:
logging.info("New refresh token found, updating!")
refresh_data["refresh_token"] = refresh_token
util.save_to_json(refresh_data, token_path) util.save_to_json(refresh_data, token_path)
session.headers.update({"authorization": "Bearer " + refresh_data["access_token"]}) session.headers.update({"authorization": "Bearer " + refresh_data["access_token"]})
@@ -451,7 +462,9 @@ def check_engine_status(vin):
mqtt.assumed_climate_state[vin] = "OFF" mqtt.assumed_climate_state[vin] = "OFF"
mqtt.update_car_data() mqtt.update_car_data()
break break
time.sleep(5) time.sleep(5)
return None
def backend_status_loop(): def backend_status_loop():
@@ -587,196 +600,202 @@ def cached_request(url, method, vin, force_update=False, key_change=False):
def parse_api_data(data, sensor_id=None): def parse_api_data(data, sensor_id=None):
if sensor_id != "api_backend_status": if sensor_id in ["battery_charge_level", "electric_range", "charging_system_status",
data = data["data"] "charging_connection_status", "estimated_charging_time", "estimated_charging_finish_time"]:
if sensor_id == "battery_charge_level":
return data["batteryChargeLevel"]["value"] if util.keys_exists(data, "batteryChargeLevel") else None if sensor_id == "battery_charge_level":
elif sensor_id == "battery_capacity": return data["batteryChargeLevel"]["value"] if util.keys_exists(data, "batteryChargeLevel") else None
return data["batteryCapacityKWH"] if util.keys_exists(data, "batteryCapacityKWH") else None elif sensor_id == "electric_range":
elif sensor_id == "electric_range": return util.convert_metric_values(data["electricRange"]["value"]) \
return util.convert_metric_values(data["electricRange"]["value"]) \ if util.keys_exists(data, "electricRange") else None
if util.keys_exists(data, "electricRange") else None elif sensor_id == "charging_system_status":
elif sensor_id == "charging_system_status": return charging_system_states[data["chargingStatus"]["value"]] \
return charging_system_states[data["chargingSystemStatus"]["value"]] \ if util.keys_exists(data, "chargingStatus") else None
if util.keys_exists(data, "chargingSystemStatus") else None elif sensor_id == "charging_connection_status":
elif sensor_id == "charging_connection_status": return charging_connection_states[data["chargerConnectionStatus"]["value"]] \
return charging_connection_states[data["chargingConnectionStatus"]["value"]] \ if util.keys_exists(data, "chargerConnectionStatus") else None
if util.keys_exists(data, "chargingConnectionStatus") else None elif sensor_id == "estimated_charging_time":
elif sensor_id == "estimated_charging_time": if util.keys_exists(data, "chargingStatus"):
if util.keys_exists(data, "chargingSystemStatus"): charging_system_state = charging_system_states[data["chargingStatus"]["value"]]
charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] if charging_system_state == "Charging":
if charging_system_state == "Charging": return data["estimatedChargingTimeToTargetBatteryChargeLevel"]["value"] if util.keys_exists(data,
return data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") else "" "estimatedChargingTimeToTargetBatteryChargeLevel") else ""
else:
return 0
return None
elif sensor_id == "estimated_charging_finish_time":
if util.keys_exists(data, "estimatedChargingTimeToTargetBatteryChargeLevel"):
charging_system_state = charging_system_states[data["chargingStatus"]["value"]]
if charging_system_state == "Charging":
charging_time = int(
data["estimatedChargingTimeToTargetBatteryChargeLevel"]["value"] if util.keys_exists(data, "estimatedChargingTimeToTargetBatteryChargeLevel")
else 0)
charging_finished = datetime.now(util.TZ) + timedelta(minutes=charging_time)
return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"])
else:
return ""
return None
return None
else:
if sensor_id != "api_backend_status":
data = data["data"]
if sensor_id == "lock_status":
return data["centralLock"]["value"] if util.keys_exists(data, "centralLock") else None
elif sensor_id == "battery_capacity":
return data["batteryCapacityKWH"] if util.keys_exists(data, "batteryCapacityKWH") else None
elif sensor_id == "odometer":
return util.convert_metric_values(int(data["odometer"]["value"])) \
if util.keys_exists(data, "odometer") else None
elif sensor_id == "window_front_left":
return window_states[data["frontLeftWindow"]["value"]] if util.keys_exists(data, "frontLeftWindow") \
else None
elif sensor_id == "window_front_right":
return window_states[data["frontRightWindow"]["value"]] if util.keys_exists(data, "frontRightWindow") \
else None
elif sensor_id == "window_rear_left":
return window_states[data["rearLeftWindow"]["value"]] if util.keys_exists(data, "rearLeftWindow") \
else None
elif sensor_id == "window_rear_right":
return window_states[data["rearRightWindow"]["value"]] if util.keys_exists(data, "rearRightWindow") \
else None
elif sensor_id == "door_front_left":
return door_states[data["frontLeftDoor"]["value"]] if util.keys_exists(data, "frontLeftDoor") else None
elif sensor_id == "door_front_right":
return door_states[data["frontRightDoor"]["value"]] \
if util.keys_exists(data, "frontRightDoor") else None
elif sensor_id == "door_rear_left":
return door_states[data["rearLeftDoor"]["value"]] if util.keys_exists(data, "rearLeftDoor") else None
elif sensor_id == "door_rear_right":
return door_states[data["rearRightDoor"]["value"]] if util.keys_exists(data, "rearRightDoor") else None
elif sensor_id == "tailgate":
return door_states[data["tailgate"]["value"]] if util.keys_exists(data, "tailgate") else None
elif sensor_id == "sunroof":
return door_states[data["sunroof"]["value"]] if util.keys_exists(data, "sunroof") else None
elif sensor_id == "engine_hood":
return door_states[data["hood"]["value"]] if util.keys_exists(data, "hood") else None
elif sensor_id == "tank_lid":
return door_states[data["tankLid"]["value"]] if util.keys_exists(data, "tankLid") else None
elif sensor_id == "tyre_front_left":
return data["frontLeft"]["value"] if util.keys_exists(data, "frontLeft") else None
elif sensor_id == "tyre_front_right":
return data["frontRight"]["value"] if util.keys_exists(data, "frontRight") else None
elif sensor_id == "tyre_rear_left":
return data["rearLeft"]["value"] if util.keys_exists(data, "rearLeft") else None
elif sensor_id == "tyre_rear_right":
return data["rearRight"]["value"] if util.keys_exists(data, "rearRight") else None
elif sensor_id == "engine_state":
return engine_states[data["engineStatus"]["value"]] if util.keys_exists(data, "engineStatus") else None
elif sensor_id == "fuel_level":
if util.keys_exists(data, "fuelAmount"):
fuel_amount = float(data["fuelAmount"]["value"])
if fuel_amount > 0:
return fuel_amount
return None
elif sensor_id == "average_fuel_consumption":
average_fuel_con = 0
if util.keys_exists(data, "averageFuelConsumption"):
average_fuel_con = float(data["averageFuelConsumption"]["value"])
elif util.keys_exists(data, "averageFuelConsumptionAutomatic"):
average_fuel_con = float(data["averageFuelConsumptionAutomatic"]["value"])
if average_fuel_con > 0:
return average_fuel_con
return None
elif sensor_id == "average_speed":
average_speed = 0
if util.keys_exists(data, "averageSpeed"):
average_speed = float(data["averageSpeed"]["value"])
elif util.keys_exists(data, "averageSpeedAutomatic"):
average_speed = float(data["averageSpeedAutomatic"]["value"])
if average_speed != 0:
return util.convert_metric_values(average_speed)
return None
elif sensor_id == "location":
coordinates = {}
if util.keys_exists(data, "geometry"):
raw_data = data["geometry"]
if util.keys_exists(raw_data, "coordinates"):
coordinates = {"longitude": raw_data["coordinates"][0],
"latitude": raw_data["coordinates"][1],
"gps_accuracy": 1}
return coordinates
elif sensor_id == "distance_to_empty_tank":
if util.keys_exists(data, "distanceToEmptyTank"):
distance_to_empty = int(data["distanceToEmptyTank"]["value"])
if distance_to_empty > 0:
return util.convert_metric_values(data["distanceToEmptyTank"]["value"])
return None
elif sensor_id == "distance_to_empty_battery":
if util.keys_exists(data, "distanceToEmptyBattery"):
distance_to_empty = int(data["distanceToEmptyBattery"]["value"])
if distance_to_empty > 0:
return util.convert_metric_values(data["distanceToEmptyBattery"]["value"])
return None
elif sensor_id == "hours_to_service":
return data["engineHoursToService"]["value"] if util.keys_exists(data, "engineHoursToService") else None
elif sensor_id == "km_to_service":
if util.keys_exists(data, "distanceToService"):
km_to_service = int(data["distanceToService"]["value"])
if km_to_service > 0:
return util.convert_metric_values(data["distanceToService"]["value"])
return None
elif sensor_id == "time_to_service":
if util.keys_exists(data, "timeToService"):
return str(data["timeToService"]["value"]) + " " + data["timeToService"]["unit"]
else: else:
return 0 return None
return None elif sensor_id == "service_warning_status":
elif sensor_id == "estimated_charging_finish_time": return data["serviceWarning"]["value"] if util.keys_exists(data, "serviceWarning") else None
if util.keys_exists(data, "chargingSystemStatus"): elif sensor_id == "average_energy_consumption":
charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] average_energy_con = 0
if charging_system_state == "Charging": if util.keys_exists(data, "averageEnergyConsumption"):
charging_time = int( average_energy_con = data["averageEnergyConsumption"]["value"]
data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") elif util.keys_exists(data, "averageEnergyConsumptionAutomatic"):
else 0) average_energy_con = data["averageEnergyConsumptionAutomatic"]["value"]
charging_finished = datetime.now(util.TZ) + timedelta(minutes=charging_time)
return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"])
else:
return ""
return None
elif sensor_id == "lock_status":
return data["centralLock"]["value"] if util.keys_exists(data, "centralLock") else None
elif sensor_id == "odometer":
return util.convert_metric_values(int(data["odometer"]["value"])) \
if util.keys_exists(data, "odometer") else None
elif sensor_id == "window_front_left":
return window_states[data["frontLeftWindow"]["value"]] if util.keys_exists(data, "frontLeftWindow") \
else None
elif sensor_id == "window_front_right":
return window_states[data["frontRightWindow"]["value"]] if util.keys_exists(data, "frontRightWindow") \
else None
elif sensor_id == "window_rear_left":
return window_states[data["rearLeftWindow"]["value"]] if util.keys_exists(data, "rearLeftWindow") \
else None
elif sensor_id == "window_rear_right":
return window_states[data["rearRightWindow"]["value"]] if util.keys_exists(data, "rearRightWindow") \
else None
elif sensor_id == "door_front_left":
return door_states[data["frontLeftDoor"]["value"]] if util.keys_exists(data, "frontLeftDoor") else None
elif sensor_id == "door_front_right":
return door_states[data["frontRightDoor"]["value"]] \
if util.keys_exists(data, "frontRightDoor") else None
elif sensor_id == "door_rear_left":
return door_states[data["rearLeftDoor"]["value"]] if util.keys_exists(data, "rearLeftDoor") else None
elif sensor_id == "door_rear_right":
return door_states[data["rearRightDoor"]["value"]] if util.keys_exists(data, "rearRightDoor") else None
elif sensor_id == "tailgate":
return door_states[data["tailgate"]["value"]] if util.keys_exists(data, "tailgate") else None
elif sensor_id == "sunroof":
return door_states[data["sunroof"]["value"]] if util.keys_exists(data, "sunroof") else None
elif sensor_id == "engine_hood":
return door_states[data["hood"]["value"]] if util.keys_exists(data, "hood") else None
elif sensor_id == "tank_lid":
return door_states[data["tankLid"]["value"]] if util.keys_exists(data, "tankLid") else None
elif sensor_id == "tyre_front_left":
return data["frontLeft"]["value"] if util.keys_exists(data, "frontLeft") else None
elif sensor_id == "tyre_front_right":
return data["frontRight"]["value"] if util.keys_exists(data, "frontRight") else None
elif sensor_id == "tyre_rear_left":
return data["rearLeft"]["value"] if util.keys_exists(data, "rearLeft") else None
elif sensor_id == "tyre_rear_right":
return data["rearRight"]["value"] if util.keys_exists(data, "rearRight") else None
elif sensor_id == "engine_state":
return engine_states[data["engineStatus"]["value"]] if util.keys_exists(data, "engineStatus") else None
elif sensor_id == "fuel_level":
if util.keys_exists(data, "fuelAmount"):
fuel_amount = float(data["fuelAmount"]["value"])
if fuel_amount > 0:
return fuel_amount
return None
elif sensor_id == "average_fuel_consumption":
average_fuel_con = 0
if util.keys_exists(data, "averageFuelConsumption"):
average_fuel_con = float(data["averageFuelConsumption"]["value"])
elif util.keys_exists(data, "averageFuelConsumptionAutomatic"):
average_fuel_con = float(data["averageFuelConsumptionAutomatic"]["value"])
if average_fuel_con > 0: if average_energy_con != 0:
return average_fuel_con return average_energy_con
return None return None
elif sensor_id == "average_speed": elif sensor_id == "washer_fluid_warning":
average_speed = 0 return data["washerFluidLevelWarning"]["value"] if util.keys_exists(data, "washerFluidLevelWarning") else None
if util.keys_exists(data, "averageSpeed"): elif sensor_id == "warnings":
average_speed = float(data["averageSpeed"]["value"]) warnings = 0
elif util.keys_exists(data, "averageSpeedAutomatic"): cleaned_data = {}
average_speed = float(data["averageSpeedAutomatic"]["value"]) for key, dicts in data.items():
contains_data = sum(value == "NO_WARNING" or value == "FAILURE" for value in dicts.values())
if contains_data:
warnings = warnings + 1
cleaned_data[key] = dicts["value"]
if average_speed != 0: return cleaned_data if warnings > 0 else None
return util.convert_metric_values(average_speed) elif sensor_id == "trip_fuel_consumption":
trip_fuel_con = 0
return None if util.keys_exists(data, "averageFuelConsumptionAutomatic"):
elif sensor_id == "location": trip_fuel_con = float(data["averageFuelConsumptionAutomatic"]["value"])
coordinates = {} if trip_fuel_con > 0:
if util.keys_exists(data, "geometry"): return trip_fuel_con
raw_data = data["geometry"] return None
if util.keys_exists(raw_data, "coordinates"): elif sensor_id == "trip_distance":
coordinates = {"longitude": raw_data["coordinates"][0], return util.convert_metric_values(int(data["tripMeterAutomatic"]["value"])) \
"latitude": raw_data["coordinates"][1], if util.keys_exists(data, "tripMeterAutomatic") else None
"gps_accuracy": 1} elif sensor_id == "trip_energy_consumption":
return coordinates trip_energy_con = 0
elif sensor_id == "distance_to_empty_tank": if util.keys_exists(data, "averageEnergyConsumptionAutomatic"):
if util.keys_exists(data, "distanceToEmptyTank"): trip_energy_con = data["averageEnergyConsumptionAutomatic"]["value"]
distance_to_empty = int(data["distanceToEmptyTank"]["value"]) if trip_energy_con != 0:
if distance_to_empty > 0: return trip_energy_con
return util.convert_metric_values(data["distanceToEmptyTank"]["value"]) return None
return None elif sensor_id == "trip_speed":
elif sensor_id == "distance_to_empty_battery": trip_speed = 0
if util.keys_exists(data, "distanceToEmptyBattery"): if util.keys_exists(data, "averageSpeedAutomatic"):
distance_to_empty = int(data["distanceToEmptyBattery"]["value"]) trip_speed = float(data["averageSpeedAutomatic"]["value"])
if distance_to_empty > 0: if trip_speed != 0:
return util.convert_metric_values(data["distanceToEmptyBattery"]["value"]) return util.convert_metric_values(trip_speed)
return None return None
elif sensor_id == "hours_to_service":
return data["engineHoursToService"]["value"] if util.keys_exists(data, "engineHoursToService") else None
elif sensor_id == "km_to_service":
if util.keys_exists(data, "distanceToService"):
km_to_service = int(data["distanceToService"]["value"])
if km_to_service > 0:
return util.convert_metric_values(data["distanceToService"]["value"])
return None
elif sensor_id == "time_to_service":
if util.keys_exists(data, "timeToService"):
return str(data["timeToService"]["value"]) + " " + data["timeToService"]["unit"]
else: else:
return None return None
elif sensor_id == "service_warning_status":
return data["serviceWarning"]["value"] if util.keys_exists(data, "serviceWarning") else None
elif sensor_id == "average_energy_consumption":
average_energy_con = 0
if util.keys_exists(data, "averageEnergyConsumption"):
average_energy_con = data["averageEnergyConsumption"]["value"]
elif util.keys_exists(data, "averageEnergyConsumptionAutomatic"):
average_energy_con = data["averageEnergyConsumptionAutomatic"]["value"]
if average_energy_con != 0:
return average_energy_con
return None
elif sensor_id == "washer_fluid_warning":
return data["washerFluidLevelWarning"]["value"] if util.keys_exists(data, "washerFluidLevelWarning") else None
elif sensor_id == "warnings":
warnings = 0
cleaned_data = {}
for key, dicts in data.items():
contains_data = sum(value == "NO_WARNING" or value == "FAILURE" for value in dicts.values())
if contains_data:
warnings = warnings + 1
cleaned_data[key] = dicts["value"]
return cleaned_data if warnings > 0 else None
elif sensor_id == "trip_fuel_consumption":
trip_fuel_con = 0
if util.keys_exists(data, "averageFuelConsumptionAutomatic"):
trip_fuel_con = float(data["averageFuelConsumptionAutomatic"]["value"])
if trip_fuel_con > 0:
return trip_fuel_con
return None
elif sensor_id == "trip_distance":
return util.convert_metric_values(int(data["tripMeterAutomatic"]["value"])) \
if util.keys_exists(data, "tripMeterAutomatic") else None
elif sensor_id == "trip_energy_consumption":
trip_energy_con = 0
if util.keys_exists(data, "averageEnergyConsumptionAutomatic"):
trip_energy_con = data["averageEnergyConsumptionAutomatic"]["value"]
if trip_energy_con != 0:
return trip_energy_con
return None
elif sensor_id == "trip_speed":
trip_speed = 0
if util.keys_exists(data, "averageSpeedAutomatic"):
trip_speed = float(data["averageSpeedAutomatic"]["value"])
if trip_speed != 0:
return util.convert_metric_values(trip_speed)
return None
else:
return None