forked from peter/volvo2mqtt
Add support for multiple vehicles
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user