Add support for multiple vehicles

This commit is contained in:
Linus Dietz
2023-06-19 19:46:06 +02:00
parent 298e8b503a
commit 21cb2999f7
2 changed files with 137 additions and 129 deletions
+119 -117
View File
@@ -80,132 +80,134 @@ def update_loop():
def update_car_data(): def update_car_data():
global last_data_update global last_data_update
last_data_update = format_datetime(datetime.now(), format="medium", locale=settings["babelLocale"]) last_data_update = format_datetime(datetime.now(), format="medium", locale=settings["babelLocale"])
for lock in supported_locks: for vin in volvo.vins:
state = volvo.api_call(lock["url"], "GET", lock["id"]) for lock in supported_locks:
mqtt_client.publish( state = volvo.api_call(lock["url"], "GET", vin, lock["id"])
f"homeassistant/lock/{volvo.vin}_{lock['id']}/state", mqtt_client.publish(
state f"homeassistant/lock/{vin}_{lock['id']}/state",
) state
)
for switch in supported_switches: for switch in supported_switches:
if switch["id"] == "climate_status": if switch["id"] == "climate_status":
state = assumed_climate_state state = assumed_climate_state
else: else:
state = "OFF" state = "OFF"
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/switch/{volvo.vin}_{switch['id']}/state", f"homeassistant/switch/{vin}_{switch['id']}/state",
state state
) )
for sensor in supported_sensors: for sensor in supported_sensors:
if sensor["id"] == "last_data_update": if sensor["id"] == "last_data_update":
state = last_data_update state = last_data_update
else: else:
state = volvo.api_call(sensor["url"], "GET", sensor["id"]) state = volvo.api_call(sensor["url"], "GET", vin, sensor["id"])
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/sensor/{volvo.vin}_{sensor['id']}/state", f"homeassistant/sensor/{vin}_{sensor['id']}/state",
state state
) )
def create_ha_devices(): def create_ha_devices():
car_details = volvo.api_call(VEHICLE_DETAILS_URL, "GET") for vin in volvo.vins:
car_details = volvo.api_call(VEHICLE_DETAILS_URL, "GET", vin)
for button in supported_buttons: for button in supported_buttons:
command_topic = f"homeassistant/button/{volvo.vin}_{button['id']}/command" command_topic = f"homeassistant/button/{vin}_{button['id']}/command"
config = { config = {
"name": button['name'], "name": button['name'],
"object_id": button['id'], "object_id": button['id'],
"schema": "state", "schema": "state",
"icon": f"mdi:{button['icon']}", "icon": f"mdi:{button['icon']}",
"state_topic": f"homeassistant/button/{volvo.vin}_{button['id']}/state", "state_topic": f"homeassistant/button/{vin}_{button['id']}/state",
"command_topic": command_topic, "command_topic": command_topic,
"device": { "device": {
"identifiers": ["volvoAAOS2mqtt"], "identifiers": [f"volvoAAOS2mqtt_{vin}"],
"manufacturer": "Volvo", "manufacturer": "Volvo",
"model": car_details['descriptions']['model'], "model": car_details['descriptions']['model'],
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {volvo.vin}", "name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
}, },
"unique_id": f"volvoAAOS2mqtt_{volvo.vin}_{button['id']}", "unique_id": f"volvoAAOS2mqtt_{vin}_{button['id']}",
} }
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/button/volvoAAOS2mqtt/{volvo.vin}_{button['id']}/config", f"homeassistant/button/volvoAAOS2mqtt/{vin}_{button['id']}/config",
json.dumps(config), json.dumps(config),
) )
subscribed_topics.append(command_topic) subscribed_topics.append(command_topic)
mqtt_client.subscribe(command_topic) mqtt_client.subscribe(command_topic)
for lock in supported_locks: for lock in supported_locks:
command_topic = f"homeassistant/lock/{volvo.vin}_{lock['id']}/command" command_topic = f"homeassistant/lock/{vin}_{lock['id']}/command"
config = { config = {
"name": lock['name'], "name": lock['name'],
"object_id": lock['id'], "object_id": lock['id'],
"schema": "state", "schema": "state",
"icon": f"mdi:{lock['icon']}", "icon": f"mdi:{lock['icon']}",
"state_topic": f"homeassistant/lock/{volvo.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": {
"identifiers": ["volvoAAOS2mqtt"], "identifiers": [f"volvoAAOS2mqtt_{vin}"],
"manufacturer": "Volvo", "manufacturer": "Volvo",
"model": car_details['descriptions']['model'], "model": car_details['descriptions']['model'],
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {volvo.vin}", "name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
}, },
"unique_id": f"volvoAAOS2mqtt_{volvo.vin}_{lock['id']}", "unique_id": f"volvoAAOS2mqtt_{vin}_{lock['id']}",
} }
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/lock/volvoAAOS2mqtt/{volvo.vin}_{lock['id']}/config", f"homeassistant/lock/volvoAAOS2mqtt/{vin}_{lock['id']}/config",
json.dumps(config), json.dumps(config),
) )
subscribed_topics.append(command_topic) subscribed_topics.append(command_topic)
mqtt_client.subscribe(command_topic) mqtt_client.subscribe(command_topic)
for switch in supported_switches: for switch in supported_switches:
command_topic = f"homeassistant/switch/{volvo.vin}_{switch['id']}/command" command_topic = f"homeassistant/switch/{vin}_{switch['id']}/command"
config = { config = {
"name": switch['name'], "name": switch['name'],
"object_id": switch['id'], "object_id": switch['id'],
"schema": "state", "schema": "state",
"icon": f"mdi:{switch['icon']}", "icon": f"mdi:{switch['icon']}",
"state_topic": f"homeassistant/switch/{volvo.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": {
"identifiers": ["volvoAAOS2mqtt"], "identifiers": [f"volvoAAOS2mqtt_{vin}"],
"manufacturer": "Volvo", "manufacturer": "Volvo",
"model": car_details['descriptions']['model'], "model": car_details['descriptions']['model'],
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {volvo.vin}", "name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
}, },
"unique_id": f"volvoAAOS2mqtt_{volvo.vin}_{switch['id']}", "unique_id": f"volvoAAOS2mqtt_{vin}_{switch['id']}",
} }
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/switch/volvoAAOS2mqtt/{volvo.vin}_{switch['id']}/config", f"homeassistant/switch/volvoAAOS2mqtt/{vin}_{switch['id']}/config",
json.dumps(config), json.dumps(config),
) )
subscribed_topics.append(command_topic) subscribed_topics.append(command_topic)
mqtt_client.subscribe(command_topic) mqtt_client.subscribe(command_topic)
for sensor in supported_sensors: for sensor in supported_sensors:
config = { config = {
"name": sensor['name'], "name": sensor['name'],
"object_id": sensor['id'], "object_id": sensor['id'],
"schema": "state", "schema": "state",
"icon": f"mdi:{sensor['icon']}", "icon": f"mdi:{sensor['icon']}",
"state_topic": f"homeassistant/sensor/{volvo.vin}_{sensor['id']}/state", "state_topic": f"homeassistant/sensor/{vin}_{sensor['id']}/state",
"device": { "device": {
"identifiers": ["volvoAAOS2mqtt"], "identifiers": [f"volvoAAOS2mqtt_{vin}"],
"manufacturer": "Volvo", "manufacturer": "Volvo",
"model": car_details['descriptions']['model'], "model": car_details['descriptions']['model'],
"name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {volvo.vin}", "name": f"{car_details['descriptions']['model']} ({car_details['modelYear']}) - {vin}",
}, },
"unique_id": f"volvoAAOS2mqtt_{volvo.vin}_{sensor['id']}", "unique_id": f"volvoAAOS2mqtt_{vin}_{sensor['id']}",
} }
if "unit" in sensor: if "unit" in sensor:
config["unit_of_measurement"] = sensor["unit"] config["unit_of_measurement"] = sensor["unit"]
mqtt_client.publish( mqtt_client.publish(
f"homeassistant/sensor/volvoAAOS2mqtt/{volvo.vin}_{sensor['id']}/config", f"homeassistant/sensor/volvoAAOS2mqtt/{vin}_{sensor['id']}/config",
json.dumps(config), json.dumps(config),
) )
time.sleep(2) time.sleep(2)
+18 -12
View File
@@ -15,7 +15,7 @@ session.headers = {
token_expires_at: datetime token_expires_at: datetime
refresh_token = None refresh_token = None
vin = "" vins = []
recharge_response = {} recharge_response = {}
recharge_last_update = None recharge_last_update = None
@@ -42,7 +42,7 @@ def authorize():
token_expires_at = datetime.now() + timedelta(seconds=(data["expires_in"] - 30)) token_expires_at = datetime.now() + timedelta(seconds=(data["expires_in"] - 30))
refresh_token = data["refresh_token"] refresh_token = data["refresh_token"]
get_vehicle() get_vehicles()
else: else:
message = auth.json() message = auth.json()
raise Exception(message["error_description"]) raise Exception(message["error_description"])
@@ -71,25 +71,31 @@ def refresh_auth():
refresh_token = data["refresh_token"] refresh_token = data["refresh_token"]
def get_vehicle(): def get_vehicles():
global vin global vins
if not settings.volvoData["vin"]: if not settings.volvoData["vin"]:
vehicles = session.get(VEHICLES_URL) vehicles = session.get(VEHICLES_URL)
if vehicles.status_code == 200: if vehicles.status_code == 200:
data = vehicles.json() data = vehicles.json()
if len(data["data"]) > 0: if len(data["data"]) > 0:
vin = data["data"][0]["vin"] for vehicle in data["data"]:
vins.append(vehicle["vin"])
else: else:
print("No vehicle in account " + settings.volvoData["username"] + " found.") raise Exception("No vehicle in account " + settings.volvoData["username"] + " found.")
else: else:
print("Error getting Vehicles " + str(vehicles.status_code)) raise Exception("Error getting vehicles: " + str(vehicles.status_code))
else: else:
vin = settings.volvoData["vin"] if isinstance(settings.volvoData["vin"], list):
# If setting is a list, copy
vins = settings.volvoData["vin"]
else:
# If setting is a string, append to list
vins.append(settings.volvoData["vin"])
if not vin: if len(vins) == 0:
raise Exception("No vehicle found, exiting application!") raise Exception("No vehicle found, exiting application!")
else: else:
print("Vin: " + vin + " found!") print("Vin: " + str(vins) + " found!")
def disable_climate(): def disable_climate():
@@ -97,12 +103,12 @@ def disable_climate():
mqtt.update_car_data() mqtt.update_car_data()
def api_call(url, method, sensor_id=None): def api_call(url, method, vin, sensor_id=None):
global token_expires_at global token_expires_at
if datetime.now() >= token_expires_at: if datetime.now() >= token_expires_at:
refresh_auth() refresh_auth()
global vin, recharge_response, recharge_last_update global recharge_response, recharge_last_update
if url == RECHARGE_STATUS_URL: if url == RECHARGE_STATUS_URL:
# Minimize API calls for recharge API # Minimize API calls for recharge API
if not bool(recharge_response): if not bool(recharge_response):