forked from peter/volvo2mqtt
Add value conversion from metric to imperial (#36)
* Convert km to miles, km/h to mp/h if babelLocale is en_GB or en_US #34 * Remove unused variable * Change speed unit for imperial system // Bump version
This commit is contained in:
+1
-1
@@ -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"
|
||||
|
||||
+19
-4
@@ -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}
|
||||
]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
+20
-13
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user