forked from peter/volvo2mqtt
Workaround for vehicle details error 500
This commit is contained in:
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
.idea
|
.idea
|
||||||
venv
|
venv
|
||||||
|
src/settings.dev.json
|
||||||
+1
-1
@@ -2,5 +2,5 @@ from dynaconf import Dynaconf
|
|||||||
|
|
||||||
settings = Dynaconf(
|
settings = Dynaconf(
|
||||||
envvar_prefix="CONF",
|
envvar_prefix="CONF",
|
||||||
settings_files=["settings.json", "/data/options.json"],
|
settings_files=["settings.json", "/data/options.json", "settings.dev.json"],
|
||||||
)
|
)
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: "Volvo2Mqtt"
|
name: "Volvo2Mqtt"
|
||||||
description: "Volvo AAOS MQTT bridge"
|
description: "Volvo AAOS MQTT bridge"
|
||||||
version: "1.1.1"
|
version: "1.1.2"
|
||||||
slug: "volvo2mqtt"
|
slug: "volvo2mqtt"
|
||||||
init: false
|
init: false
|
||||||
url: "https://github.com/Dielee/volvo2mqtt"
|
url: "https://github.com/Dielee/volvo2mqtt"
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VERSION = "v1.1.1"
|
VERSION = "v1.1.2"
|
||||||
|
|
||||||
OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
|
OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
|
||||||
VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v1/vehicles"
|
VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v1/vehicles"
|
||||||
|
|||||||
+12
-34
@@ -6,7 +6,7 @@ from threading import Thread, Timer
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from babel.dates import format_datetime
|
from babel.dates import format_datetime
|
||||||
from config import settings
|
from config import settings
|
||||||
from const import VEHICLE_DETAILS_URL, CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \
|
from const import CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \
|
||||||
CAR_UNLOCK_URL, supported_sensors, supported_buttons, supported_switches, supported_locks
|
CAR_UNLOCK_URL, supported_sensors, supported_buttons, supported_switches, supported_locks
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ mqtt_client: mqtt.Client
|
|||||||
subscribed_topics = []
|
subscribed_topics = []
|
||||||
assumed_climate_state = {}
|
assumed_climate_state = {}
|
||||||
last_data_update = None
|
last_data_update = None
|
||||||
climate_timer_thread: Thread
|
climate_timer: Timer
|
||||||
|
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
@@ -46,24 +46,22 @@ def on_message(client, userdata, msg):
|
|||||||
vin = msg.topic.split('/')[2].split('_')[0]
|
vin = msg.topic.split('/')[2].split('_')[0]
|
||||||
payload = msg.payload.decode("UTF-8")
|
payload = msg.payload.decode("UTF-8")
|
||||||
if "climate_status" in msg.topic:
|
if "climate_status" in msg.topic:
|
||||||
global assumed_climate_state
|
global assumed_climate_state, climate_timer
|
||||||
if payload == "ON":
|
if payload == "ON":
|
||||||
api_thread = Thread(target=volvo.api_call, args=(CLIMATE_START_URL, "POST", vin))
|
api_thread = Thread(target=volvo.api_call, args=(CLIMATE_START_URL, "POST", vin))
|
||||||
api_thread.start()
|
api_thread.start()
|
||||||
assumed_climate_state[vin] = "ON"
|
assumed_climate_state[vin] = "ON"
|
||||||
# Starting timer to disable climate after 30 mins
|
# Starting timer to disable climate after 30 mins
|
||||||
global climate_timer_thread
|
climate_timer = Timer(1 * 60, volvo.disable_climate, (vin, ))
|
||||||
climate_timer_thread = Timer(30 * 60, volvo.disable_climate, (vin, ))
|
climate_timer.start()
|
||||||
climate_timer_thread.start()
|
|
||||||
update_car_data()
|
update_car_data()
|
||||||
elif payload == "OFF":
|
elif payload == "OFF":
|
||||||
api_thread = Thread(target=volvo.api_call, args=(CLIMATE_STOP_URL, "POST", vin))
|
api_thread = Thread(target=volvo.api_call, args=(CLIMATE_STOP_URL, "POST", vin))
|
||||||
api_thread.start()
|
api_thread.start()
|
||||||
assumed_climate_state[vin] = "OFF"
|
assumed_climate_state[vin] = "OFF"
|
||||||
# Stop timer if active
|
# Stop timer if active
|
||||||
global climate_timer_thread
|
if climate_timer.is_alive():
|
||||||
if climate_timer_thread.is_alive():
|
climate_timer.cancel()
|
||||||
climate_timer_thread.cancel()
|
|
||||||
update_car_data()
|
update_car_data()
|
||||||
elif "lock_status" in msg.topic:
|
elif "lock_status" in msg.topic:
|
||||||
if payload == "LOCK":
|
if payload == "LOCK":
|
||||||
@@ -121,7 +119,7 @@ def update_car_data():
|
|||||||
|
|
||||||
def create_ha_devices():
|
def create_ha_devices():
|
||||||
for vin in volvo.vins:
|
for vin in volvo.vins:
|
||||||
car_details = volvo.api_call(VEHICLE_DETAILS_URL, "GET", vin)
|
device = volvo.get_vehicle_details(vin)
|
||||||
|
|
||||||
for button in supported_buttons:
|
for button in supported_buttons:
|
||||||
command_topic = f"homeassistant/button/{vin}_{button['id']}/command"
|
command_topic = f"homeassistant/button/{vin}_{button['id']}/command"
|
||||||
@@ -132,12 +130,7 @@ def create_ha_devices():
|
|||||||
"icon": f"mdi:{button['icon']}",
|
"icon": f"mdi:{button['icon']}",
|
||||||
"state_topic": f"homeassistant/button/{vin}_{button['id']}/state",
|
"state_topic": f"homeassistant/button/{vin}_{button['id']}/state",
|
||||||
"command_topic": command_topic,
|
"command_topic": command_topic,
|
||||||
"device": {
|
"device": device,
|
||||||
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
|
||||||
"manufacturer": "Volvo",
|
|
||||||
"model": car_details['descriptions']['model'],
|
|
||||||
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
|
|
||||||
},
|
|
||||||
"unique_id": f"volvoAAOS2mqtt_{vin}_{button['id']}",
|
"unique_id": f"volvoAAOS2mqtt_{vin}_{button['id']}",
|
||||||
}
|
}
|
||||||
mqtt_client.publish(
|
mqtt_client.publish(
|
||||||
@@ -157,12 +150,7 @@ def create_ha_devices():
|
|||||||
"state_topic": f"homeassistant/lock/{vin}_{lock['id']}/state",
|
"state_topic": f"homeassistant/lock/{vin}_{lock['id']}/state",
|
||||||
"command_topic": command_topic,
|
"command_topic": command_topic,
|
||||||
"optimistic": False,
|
"optimistic": False,
|
||||||
"device": {
|
"device": device,
|
||||||
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
|
||||||
"manufacturer": "Volvo",
|
|
||||||
"model": car_details['descriptions']['model'],
|
|
||||||
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
|
|
||||||
},
|
|
||||||
"unique_id": f"volvoAAOS2mqtt_{vin}_{lock['id']}",
|
"unique_id": f"volvoAAOS2mqtt_{vin}_{lock['id']}",
|
||||||
}
|
}
|
||||||
mqtt_client.publish(
|
mqtt_client.publish(
|
||||||
@@ -182,12 +170,7 @@ def create_ha_devices():
|
|||||||
"state_topic": f"homeassistant/switch/{vin}_{switch['id']}/state",
|
"state_topic": f"homeassistant/switch/{vin}_{switch['id']}/state",
|
||||||
"command_topic": command_topic,
|
"command_topic": command_topic,
|
||||||
"optimistic": False,
|
"optimistic": False,
|
||||||
"device": {
|
"device": device,
|
||||||
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
|
||||||
"manufacturer": "Volvo",
|
|
||||||
"model": car_details['descriptions']['model'],
|
|
||||||
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
|
|
||||||
},
|
|
||||||
"unique_id": f"volvoAAOS2mqtt_{vin}_{switch['id']}",
|
"unique_id": f"volvoAAOS2mqtt_{vin}_{switch['id']}",
|
||||||
}
|
}
|
||||||
mqtt_client.publish(
|
mqtt_client.publish(
|
||||||
@@ -204,12 +187,7 @@ def create_ha_devices():
|
|||||||
"schema": "state",
|
"schema": "state",
|
||||||
"icon": f"mdi:{sensor['icon']}",
|
"icon": f"mdi:{sensor['icon']}",
|
||||||
"state_topic": f"homeassistant/sensor/{vin}_{sensor['id']}/state",
|
"state_topic": f"homeassistant/sensor/{vin}_{sensor['id']}/state",
|
||||||
"device": {
|
"device": device,
|
||||||
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
|
||||||
"manufacturer": "Volvo",
|
|
||||||
"model": car_details['descriptions']['model'],
|
|
||||||
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
|
|
||||||
},
|
|
||||||
"unique_id": f"volvoAAOS2mqtt_{vin}_{sensor['id']}",
|
"unique_id": f"volvoAAOS2mqtt_{vin}_{sensor['id']}",
|
||||||
}
|
}
|
||||||
if "unit" in sensor:
|
if "unit" in sensor:
|
||||||
|
|||||||
+31
-5
@@ -99,6 +99,34 @@ def get_vehicles():
|
|||||||
print("Vin: " + str(vins) + " found!")
|
print("Vin: " + str(vins) + " found!")
|
||||||
|
|
||||||
|
|
||||||
|
def get_vehicle_details(vin):
|
||||||
|
response = session.get(VEHICLE_DETAILS_URL.format(vin), timeout=15)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()["data"]
|
||||||
|
if "debug" in settings:
|
||||||
|
if settings["debug"]:
|
||||||
|
print(response.text)
|
||||||
|
device = {
|
||||||
|
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
||||||
|
"manufacturer": "Volvo",
|
||||||
|
"model": data['descriptions']['model'],
|
||||||
|
"name": f"{data['descriptions']['model']} ({data['modelYear']}) - {vin}",
|
||||||
|
}
|
||||||
|
elif response.status_code == 500 and not settings.volvoData["vin"]:
|
||||||
|
# Workaround for some cars that are not returning vehicle details
|
||||||
|
device = {
|
||||||
|
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
||||||
|
"manufacturer": "Volvo",
|
||||||
|
"model": vin,
|
||||||
|
"name": f"Volvo - {vin}",
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
raise Exception("Getting vehicle details failed. Status Code: " + str(response.status_code) +
|
||||||
|
". Error: " + response.text)
|
||||||
|
|
||||||
|
return device
|
||||||
|
|
||||||
|
|
||||||
def initialize_climate(vins):
|
def initialize_climate(vins):
|
||||||
for vin in vins:
|
for vin in vins:
|
||||||
mqtt.assumed_climate_state[vin] = "OFF"
|
mqtt.assumed_climate_state[vin] = "OFF"
|
||||||
@@ -157,13 +185,11 @@ def api_call(url, method, vin, sensor_id=None):
|
|||||||
else:
|
else:
|
||||||
print("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text)
|
print("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text)
|
||||||
return ""
|
return ""
|
||||||
return parse_api_data(url, data, sensor_id)
|
return parse_api_data(data, sensor_id)
|
||||||
|
|
||||||
|
|
||||||
def parse_api_data(url, data, sensor_id=None):
|
def parse_api_data(data, sensor_id=None):
|
||||||
if url == VEHICLE_DETAILS_URL:
|
if sensor_id == "battery_charge_level":
|
||||||
return data["data"]
|
|
||||||
elif sensor_id == "battery_charge_level":
|
|
||||||
if "batteryChargeLevel" in data["data"]:
|
if "batteryChargeLevel" in data["data"]:
|
||||||
return data["data"]["batteryChargeLevel"]["value"]
|
return data["data"]["batteryChargeLevel"]["value"]
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user