diff --git a/src/config.yaml b/src/config.yaml index b0fdce8..50dafe5 100644 --- a/src/config.yaml +++ b/src/config.yaml @@ -1,6 +1,6 @@ name: "Volvo2Mqtt" description: "Volvo AAOS MQTT bridge" -version: "1.5.6" +version: "1.6.0" slug: "volvo2mqtt" init: false url: "https://github.com/Dielee/volvo2mqtt" diff --git a/src/const.py b/src/const.py index 9d73040..69738e1 100644 --- a/src/const.py +++ b/src/const.py @@ -1,6 +1,6 @@ from config import settings -VERSION = "v1.5.6" +VERSION = "v1.6.0" OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2" VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v1/vehicles" @@ -20,6 +20,21 @@ BATTERY_CHARGE_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehic FUEL_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/fuel" STATISTICS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/statistics" +units = { + "en_GB": { + "divider": 1.60934, + "electric_range": {"unit": "mi"}, + "odometer": {"unit": "mi"}, + "average_speed": {"unit": "mph"} + }, + "en_US": { + "divider": 1.60934, + "electric_range": {"unit": "mi"}, + "odometer": {"unit": "mi"}, + "average_speed": {"unit": "mph"} + } + } + availability_topic = "volvoAAOS2mqtt/availability" charging_system_states = {"CHARGING_SYSTEM_CHARGING": "Charging", "CHARGING_SYSTEM_IDLE": "Idle", @@ -34,12 +49,12 @@ door_states = {"CLOSED": "OFF", "OPEN": "ON"} supported_entities = [ {"name": "Battery Charge Level", "domain": "sensor", "id": "battery_charge_level", "unit": "%", "icon": "car-battery", "url": RECHARGE_STATE_URL}, {"name": "Battery Charge Level", "domain": "sensor", "id": "battery_charge_level", "unit": "%", "icon": "car-battery", "url": BATTERY_CHARGE_STATE_URL}, - {"name": "Electric Range", "domain": "sensor", "id": "electric_range", "unit": "km" if settings["babelLocale"] != "en_US" else "mi", "icon": "map-marker-distance", "url": RECHARGE_STATE_URL}, + {"name": "Electric Range", "domain": "sensor", "id": "electric_range", "unit": "km" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["electric_range"]["unit"], "icon": "map-marker-distance", "url": RECHARGE_STATE_URL}, {"name": "Estimated Charging Time", "domain": "sensor", "id": "estimated_charging_time", "unit": "minutes", "icon": "timer-sync-outline", "url": RECHARGE_STATE_URL}, {"name": "Charging System Status", "domain": "sensor", "id": "charging_system_status", "icon": "ev-station", "url": RECHARGE_STATE_URL}, {"name": "Charging Connection Status", "domain": "sensor", "id": "charging_connection_status", "icon": "ev-plug-ccs2", "url": RECHARGE_STATE_URL}, {"name": "Estimated Charging Finish Time", "domain": "sensor", "id": "estimated_charging_finish_time", "icon": "timer-sync-outline", "url": RECHARGE_STATE_URL}, - {"name": "Odometer", "domain": "sensor", "id": "odometer", "unit": "km" if settings["babelLocale"] != "en_US" else "mi", "icon": "counter", "url": ODOMETER_STATE_URL}, + {"name": "Odometer", "domain": "sensor", "id": "odometer", "unit": "km" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["odometer"]["unit"], "icon": "counter", "url": ODOMETER_STATE_URL}, {"name": "Last Data Update", "domain": "sensor", "id": "last_data_update", "icon": "timer", "url": ""}, {"name": "Window Front Left", "domain": "binary_sensor", "device_class": "window", "id": "window_front_left", "icon": "car-door-lock", "url": WINDOWS_STATE_URL}, {"name": "Window Front Right", "domain": "binary_sensor", "device_class": "window", "id": "window_front_right", "icon": "car-door-lock", "url": WINDOWS_STATE_URL}, @@ -64,5 +79,5 @@ supported_entities = [ {"name": "Engine State", "domain": "sensor", "id": "engine_state", "icon": "engine", "url": ENGINE_STATE_URL}, {"name": "Fuel Level", "domain": "sensor", "id": "fuel_level", "unit": "liters", "icon": "fuel", "url": FUEL_STATE_URL}, {"name": "Average Fuel Consumption", "domain": "sensor", "id": "average_fuel_consumption", "unit": "liters", "icon": "fuel", "url": STATISTICS_URL}, - {"name": "Average Speed", "domain": "sensor", "id": "average_speed", "unit": "km/h" if settings["babelLocale"] != "en_US" else "mp/h", "icon": "speedometer", "url": STATISTICS_URL} + {"name": "Average Speed", "domain": "sensor", "id": "average_speed", "unit": "km/h" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["average_speed"]["unit"], "icon": "speedometer", "url": STATISTICS_URL} ] diff --git a/src/main.py b/src/main.py index 15bee43..176dd60 100644 --- a/src/main.py +++ b/src/main.py @@ -3,7 +3,6 @@ from mqtt import update_loop, connect from const import VERSION from util import set_tz - if __name__ == '__main__': print("Starting volvo2mqtt version " + VERSION) set_tz() diff --git a/src/util.py b/src/util.py index 26a3d5a..39ed9a2 100644 --- a/src/util.py +++ b/src/util.py @@ -1,5 +1,6 @@ import pytz import os +from const import units from config import settings TZ = None @@ -34,3 +35,11 @@ def set_tz(): TZ = pytz.timezone(settings_tz) else: raise Exception("No timezone setting found! Please read the README!") + + +def convert_metric_values(value): + if keys_exists(units, settings["babelLocale"]): + divider = units[settings["babelLocale"]]["divider"] + return round((float(value) / divider), 2) + else: + return value diff --git a/src/volvo.py b/src/volvo.py index 3a07853..00a854c 100644 --- a/src/volvo.py +++ b/src/volvo.py @@ -88,7 +88,8 @@ def get_vehicles(): raise Exception("No vehicle in account " + settings.volvoData["username"] + " found.") else: error = vehicles.json() - raise Exception("Error getting vehicles: " + str(vehicles.status_code) + ". " + str(error["error"].get("message"))) + raise Exception( + "Error getting vehicles: " + str(vehicles.status_code) + ". " + str(error["error"].get("message"))) else: if isinstance(settings.volvoData["vin"], list): # If setting is a list, copy @@ -224,8 +225,10 @@ def cached_request(url, method, vin, force_update=False): data = {"response": response, "last_update": datetime.now(util.TZ)} cached_requests[vin + "_" + url] = data else: - if (datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() >= settings["updateInterval"] \ - or (force_update and (datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() >= 2): + if (datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() >= settings[ + "updateInterval"] \ + or (force_update and ( + datetime.now(util.TZ) - cached_requests[vin + "_" + url]["last_update"]).total_seconds() >= 2): # Old Data in Cache, or force mode active, updating print("Starting " + method + " call against " + url) try: @@ -246,13 +249,14 @@ def parse_api_data(data, sensor_id=None): if sensor_id == "battery_charge_level": return data["batteryChargeLevel"]["value"] if util.keys_exists(data, "batteryChargeLevel") else None elif sensor_id == "electric_range": - return data["electricRange"]["value"] if util.keys_exists(data, "electricRange") else None + return util.convert_metric_values(data["electricRange"]["value"]) \ + if util.keys_exists(data, "electricRange") else None elif sensor_id == "charging_system_status": - return charging_system_states[data["chargingSystemStatus"]["value"]] if util.keys_exists(data, - "chargingSystemStatus") else None + return charging_system_states[data["chargingSystemStatus"]["value"]] \ + if util.keys_exists(data, "chargingSystemStatus") else None elif sensor_id == "charging_connection_status": - return charging_connection_states[data["chargingConnectionStatus"]["value"]] if util.keys_exists(data, - "chargingConnectionStatus") else None + return charging_connection_states[data["chargingConnectionStatus"]["value"]] \ + if util.keys_exists(data, "chargingConnectionStatus") else None elif sensor_id == "estimated_charging_time": if util.keys_exists(data, "chargingSystemStatus"): charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] @@ -266,8 +270,9 @@ def parse_api_data(data, sensor_id=None): if util.keys_exists(data, "chargingSystemStatus"): charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]] if charging_system_state == "Charging": - charging_time = int(data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") - else 0) + charging_time = int( + data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") + else 0) charging_finished = datetime.now(util.TZ) + timedelta(minutes=charging_time) return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"]) else: @@ -284,7 +289,8 @@ def parse_api_data(data, sensor_id=None): multiplier = 1 elif multiplier < 1: multiplier = 1 - return int(data["odometer"]["value"]) * multiplier if util.keys_exists(data, "odometer") else None + return util.convert_metric_values(int(data["odometer"]["value"]) * multiplier) \ + if util.keys_exists(data, "odometer") else None elif sensor_id == "window_front_left": return window_states[data["frontLeftWindowOpen"]["value"]] if util.keys_exists(data, "frontLeftWindowOpen") \ else None @@ -300,7 +306,8 @@ def parse_api_data(data, sensor_id=None): elif sensor_id == "door_front_left": return door_states[data["frontLeftDoorOpen"]["value"]] if util.keys_exists(data, "frontLeftDoorOpen") else None elif sensor_id == "door_front_right": - return door_states[data["frontRightDoorOpen"]["value"]] if util.keys_exists(data, "frontRightDoorOpen") else None + return door_states[data["frontRightDoorOpen"]["value"]] \ + if util.keys_exists(data, "frontRightDoorOpen") else None elif sensor_id == "door_rear_left": return door_states[data["rearLeftDoorOpen"]["value"]] if util.keys_exists(data, "rearLeftDoorOpen") else None elif sensor_id == "door_rear_right": @@ -359,7 +366,7 @@ def parse_api_data(data, sensor_id=None): divider = 1 elif divider < 1: divider = 1 - return average_speed / divider + return util.convert_metric_values(average_speed / divider) else: return None else: