From d07e6dfe6eb21789a04e0044ac28bd3364f13628 Mon Sep 17 00:00:00 2001 From: Linus Dietz <45101649+Dielee@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:57:30 +0100 Subject: [PATCH] Add "Time to Service" sensor --- src/CHANGELOG.md | 7 +++++++ src/config.yaml | 2 +- src/const.py | 6 ++++-- src/mqtt.py | 33 +++++++++++++++++++-------------- src/volvo.py | 10 +++++++--- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md index df5b094..05f43a8 100644 --- a/src/CHANGELOG.md +++ b/src/CHANGELOG.md @@ -1,3 +1,10 @@ +## v1.8.13 +### 🐛 Bug Fixes: + +- Add "Time to Service" sensor #125 + Breaking change: The "Months to Service" sensor will be automatically deleted. + "Time to Service" contains this information now. + ## v1.8.12 ### 🐛 Bug Fixes: diff --git a/src/config.yaml b/src/config.yaml index 80a4045..e649363 100644 --- a/src/config.yaml +++ b/src/config.yaml @@ -1,6 +1,6 @@ name: "Volvo2Mqtt" description: "Volvo AAOS MQTT bridge" -version: "1.8.12" +version: "1.8.13" slug: "volvo2mqtt" init: false url: "https://github.com/Dielee/volvo2mqtt" diff --git a/src/const.py b/src/const.py index 89791aa..9107f2a 100644 --- a/src/const.py +++ b/src/const.py @@ -1,6 +1,6 @@ from config import settings -VERSION = "v1.8.12" +VERSION = "v1.8.13" OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2" VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v1/vehicles" @@ -114,7 +114,9 @@ supported_entities = [ {"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, "state_class": "measurement"}, {"name": "Hours to Service", "domain": "sensor", "id": "hours_to_service", "unit": "hour", "icon": "wrench-clock", "url": VEHICLE_DIAGNOSTICS_URL}, {"name": "Distance to Service", "domain": "sensor", "id": "km_to_service", "unit": "km" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["distance_to_service"]["unit"], "icon": "wrench-clock", "url": VEHICLE_DIAGNOSTICS_URL}, - {"name": "Months to Service", "domain": "sensor", "id": "months_to_service", "unit": "month", "icon": "wrench-clock", "url": VEHICLE_DIAGNOSTICS_URL}, + {"name": "Time to Service", "domain": "sensor", "id": "time_to_service", "icon": "wrench-clock", "url": VEHICLE_DIAGNOSTICS_URL}, {"name": "Service warning status", "domain": "sensor", "id": "service_warning_status", "icon": "alert-outline", "url": VEHICLE_DIAGNOSTICS_URL}, {"name": "Service warning trigger", "domain": "sensor", "id": "service_warning_trigger", "icon": "alert-outline", "url": VEHICLE_DIAGNOSTICS_URL} ] + +old_entity_ids = ["months_to_service"] diff --git a/src/mqtt.py b/src/mqtt.py index 3139c9e..af9587d 100644 --- a/src/mqtt.py +++ b/src/mqtt.py @@ -10,8 +10,7 @@ from datetime import datetime from babel.dates import format_datetime from config import settings from const import CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \ - CAR_UNLOCK_URL, availability_topic, icon_states - + CAR_UNLOCK_URL, availability_topic, icon_states, old_entity_ids mqtt_client: mqtt.Client subscribed_topics = [] @@ -90,7 +89,7 @@ def on_connect(client, userdata, flags, rc): mqtt_client.subscribe(topic) -def on_disconnect(client, userdata, rc): +def on_disconnect(client, userdata, rc): logging.warning("MQTT disconnected, reconnecting automatically") @@ -141,7 +140,7 @@ def start_climate_timer(d, vin): return None if timer_seconds > 0: - Timer(timer_seconds, activate_climate_timer, (vin, start_datetime.isoformat(), )).start() + Timer(timer_seconds, activate_climate_timer, (vin, start_datetime.isoformat(),)).start() active_schedules[vin]["timers"].append(start_datetime.isoformat()) logging.debug("Climate timer set to " + str(start_datetime)) update_car_data() @@ -293,7 +292,7 @@ def update_ha_device(entity, vin, state): if entity.get("state_class"): config["state_class"] = entity["state_class"] - + if entity.get("domain") == "device_tracker": config["json_attributes_topic"] = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/attributes" @@ -317,15 +316,15 @@ def create_ha_devices(): devices[vin] = device for entity in volvo.supported_endpoints[vin]: config = { - "name": entity['name'], - "object_id": f"volvo_{vin}_{entity['id']}", - "schema": "state", - "icon": f"mdi:{entity['icon']}", - "state_topic": f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/state", - "device": device, - "unique_id": f"volvoAAOS2mqtt_{vin}_{entity['id']}", - "availability_topic": availability_topic - } + "name": entity['name'], + "object_id": f"volvo_{vin}_{entity['id']}", + "schema": "state", + "icon": f"mdi:{entity['icon']}", + "state_topic": f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/state", + "device": device, + "unique_id": f"volvoAAOS2mqtt_{vin}_{entity['id']}", + "availability_topic": availability_topic + } if entity.get("device_class"): config["device_class"] = entity["device_class"] @@ -361,3 +360,9 @@ def send_heartbeat(): def send_offline(): mqtt_client.publish(availability_topic, "offline") + +def delete_old_entities(): + for vin in volvo.vins: + for entity in old_entity_ids: + topic = f"homeassistant/sensor/volvoAAOS2mqtt/{vin}_{entity}/config" + mqtt_client.publish(topic, payload="", retain=True) diff --git a/src/volvo.py b/src/volvo.py index 9fe8f11..fbdc1e9 100644 --- a/src/volvo.py +++ b/src/volvo.py @@ -116,6 +116,7 @@ def get_vehicles(): else: initialize_climate(vins) initialize_scheduler(vins) + mqtt.delete_old_entities() logging.info("Vin: " + str(vins) + " found!") @@ -364,7 +365,7 @@ def api_call(url, method, vin, sensor_id=None, force_update=False, key_change=Fa return None elif response.status_code == 403 and "message" in data: if "Out of call volume quota" in data["message"]: - logging.warn("Quota extended. Try to change VCCAPIKEY!") + logging.warning("Quota extended. Try to change VCCAPIKEY!") change_vcc_api_key() api_call(url, method, vin, sensor_id, force_update, True) else: @@ -548,8 +549,11 @@ def parse_api_data(data, sensor_id=None): if km_to_service > 0: return util.convert_metric_values(data["distanceToService"]["value"]) return None - elif sensor_id == "months_to_service": - return data["timeToService"]["value"] if util.keys_exists(data, "timeToService") else None + elif sensor_id == "time_to_service": + if util.keys_exists(data, "timeToService"): + return str(data["timeToService"]["value"]) + " " + data["timeToService"]["unit"] + else: + return None elif sensor_id == "service_warning_status": return data["serviceWarning"]["value"] if util.keys_exists(data, "serviceWarning") else None elif sensor_id == "service_warning_trigger":