From d55dc25647cba45f4effc63ef22721acd7c09184 Mon Sep 17 00:00:00 2001 From: Linus Dietz <45101649+Dielee@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:14:20 +0100 Subject: [PATCH] Add engine runtime number and engine start switch entities --- src/const.py | 6 +++++- src/mqtt.py | 10 ++++++++-- src/volvo.py | 14 +++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/const.py b/src/const.py index 362a78f..c8a1fd2 100644 --- a/src/const.py +++ b/src/const.py @@ -22,6 +22,8 @@ ENGINE_DIAGNOSTICS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicle VEHICLE_DIAGNOSTICS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/diagnostics" API_BACKEND_STATUS_URL = "https://oip-dev-bff.euwest1.production.volvo.care/api/v1/backend-status" SUPPORTED_COMMANDS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands" +ENGINE_START_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/engine-start" +ENGINE_STOP_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/commands/engine-stop" units = { "en_GB": { @@ -101,6 +103,9 @@ supported_entities = [ {"name": "Tank Lid", "domain": "binary_sensor", "device_class": "door", "id": "tank_lid", "icon": "car-door-lock", "url": LOCK_STATE_URL}, {"name": "Sunroof", "domain": "binary_sensor", "device_class": "door", "id": "sunroof", "icon": "car-door-lock", "url": WINDOWS_STATE_URL}, {"name": "Air Conditioning", "domain": "switch", "id": "climate_status", "icon": "air-conditioner", "commands": ["CLIMATIZATION_START", "CLIMATIZATION_STOP"]}, + {"name": "Engine State", "domain": "switch", "id": "engine_state", "icon": "engine", "url": ENGINE_STATE_URL ,"commands": ["ENGINE_START", "ENGINE_STOP"]}, + {"name": "Engine Runtime", "domain": "number", "id": "engine_runtime", "unit": "minutes", "icon": "timer-sand", "commands": ["ENGINE_START", "ENGINE_STOP"], "min": 1, "max": 15, "mode": "box"}, + {"name": "Engine State", "domain": "binary_sensor", "device_class": "running", "id": "engine_state", "icon": "engine", "url": ENGINE_STATE_URL}, {"name": "Lock state", "domain": "lock", "id": "lock_status", "icon": "lock", "url": LOCK_STATE_URL, "commands": ["LOCK", "UNLOCK"]}, {"name": "Force Update Data", "domain": "button", "id": "update_data", "icon": "update", "url": ""}, {"name": "Location", "domain": "device_tracker", "id": "location", "icon": "map-marker-radius", "url": LOCATION_STATE_URL}, @@ -108,7 +113,6 @@ supported_entities = [ {"name": "Tire Front Right", "domain": "sensor", "id": "tyre_front_right", "icon": "car-tire-alert", "url": TYRE_STATE_URL}, {"name": "Tire Rear Left", "domain": "sensor", "id": "tyre_rear_left", "icon": "car-tire-alert", "url": TYRE_STATE_URL}, {"name": "Tire Rear Right", "domain": "sensor", "id": "tyre_rear_right", "icon": "car-tire-alert", "url": TYRE_STATE_URL}, - {"name": "Engine State", "domain": "binary_sensor", "device_class": "running", "id": "engine_state", "icon": "engine", "url": ENGINE_STATE_URL}, {"name": "Fuel Level", "domain": "sensor", "id": "fuel_level", "unit": "liters", "icon": "fuel", "url": FUEL_BATTERY_STATE_URL, "state_class": "measurement"}, {"name": "Average Fuel Consumption", "domain": "sensor", "id": "average_fuel_consumption", "unit": "liters", "icon": "fuel", "url": STATISTICS_URL}, {"name": "Average Energy Consumption", "domain": "sensor", "id": "average_energy_consumption", "unit": "kwh", "icon": "car-electric", "url": STATISTICS_URL}, diff --git a/src/mqtt.py b/src/mqtt.py index 5a213d3..e9d3689 100644 --- a/src/mqtt.py +++ b/src/mqtt.py @@ -226,7 +226,7 @@ def update_car_data(force_update=False, overwrite={}): last_data_update = format_datetime(datetime.now(util.TZ), format="medium", locale=settings["babelLocale"]) for vin in volvo.vins: for entity in volvo.supported_endpoints[vin]: - if entity["domain"] == "button": + if entity["domain"] in ["button", "number"]: continue ov_entity_id = "" @@ -344,11 +344,17 @@ def create_ha_devices(): if entity.get("domain") == "device_tracker" or entity.get("id") == "active_schedules": config["json_attributes_topic"] = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/attributes" - elif entity.get("domain") in ["switch", "lock", "button"]: + elif entity.get("domain") in ["switch", "lock", "button", "number"]: command_topic = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/command" config["command_topic"] = command_topic subscribed_topics.append(command_topic) mqtt_client.subscribe(command_topic) + + if entity["domain"] == "number": + config["min"] = entity["min"] + config["max"] = entity["max"] + config["mode"] = entity["mode"] + elif entity.get("domain") == "image": config["url_topic"] = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/image_url" diff --git a/src/volvo.py b/src/volvo.py index dde6ecf..a704135 100644 --- a/src/volvo.py +++ b/src/volvo.py @@ -12,7 +12,8 @@ from json import JSONDecodeError 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, \ WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, supported_entities, FUEL_BATTERY_STATE_URL, \ - STATISTICS_URL, ENGINE_DIAGNOSTICS_URL, API_BACKEND_STATUS_URL, SUPPORTED_COMMANDS_URL, engine_states + STATISTICS_URL, ENGINE_DIAGNOSTICS_URL, API_BACKEND_STATUS_URL, SUPPORTED_COMMANDS_URL, \ + ENGINE_STATE_URL, engine_states session = requests.Session() session.headers = { @@ -261,6 +262,12 @@ def check_supported_endpoints(): # If battery charge level could be found in recharge-api, skip the second battery charge sensor continue + if entity["id"] == "engine_state" and entity["url"] == ENGINE_STATE_URL \ + and any("engine_state" in d["id"] for d in supported_endpoints[vin]): + # If engine state is supported with commands, skip engine state sensor, as switch + # represents the actual engine state + continue + if entity["domain"] in ["switch", "lock"]: state = check_supported_command(entity["commands"]) else: @@ -270,10 +277,10 @@ def check_supported_endpoints(): state = "" if state is not None: - logging.info("Success! " + entity["name"] + " is supported by your vehicle.") + logging.info("Success! " + entity["name"] + " (" + entity["domain"] + ") is supported by your vehicle.") supported_endpoints[vin].append(entity) else: - logging.info("Failed, " + entity["name"] + " is unfortunately not supported by your vehicle.") + logging.info("Failed, " + entity["name"] + " (" + entity["domain"] + ") is unfortunately not supported by your vehicle.") def check_supported_command(entity_commands): @@ -281,6 +288,7 @@ def check_supported_command(entity_commands): for entity_command in entity_commands: if entity_command not in supported_commands: commands_supported = False + break if commands_supported: return ""